GNU GRUB(简称“GRUB”)是一个来自GNU项目的启动引导程序。GRUB是多启动规范的实现,它允许用户可以在计算机内同时拥有多个操作系统,并在计算机启动时选择希望运行的操作系统。GRUB可用于选择操作系统分区上的不同内核,也可用于向这些内核传递启动参数。
简单解释出来,可以把GRUB理解成嵌入式系统中常说的bootloader。只不过主流嵌入式系统大部分是基于RISC(ARM/MIPS/PowerPC)指令集处理器架构的,而这些嵌入式系统上电引导时使用的bootloeader也都是基于uboot改造而来的。
目前 GRUB 分成 GRUB legacy 和 GRUB 2。版本号是 0.9x 以及之前的版本都称为 GRUB Legacy ,从 1.x 开始的就称为 GRUB 2。
本文介绍的GRUB基于1.99版本,实际内容还是以GRUB Legacy使用为主,简单介绍一下工作中用到过的几个命令。
进入到GRUB界面之后,通常显示如下命令:
GNU GRUB version 1.99
Minimal BASH-like line editing is supported. For the first word, TAB lists possible command completions. Anywhere else TAB lists possible device or file completions. ESC at any time exits.
grub>
此时执行tab命令,会显示一系列GRUB命令行下可执行命令提示:
Possible commands are:
. [ acpi authenticate background_image badram blocklist boot break cat chainloader clear cmosclean cmostest cmp configfile continue cpuid crc cutmem
date drivemap dump echo efiemu_loadcore efiemu_prepare efiemu_unload exit export extract_entries_configfile extract_entries_source extract_legacy_entries_configfile extract_legacy_entries_source false functional_test gettext gptsync halt hashsum hdparm hello help hexdump inb initrd initrd16 inl insmod inw keymap keystatus kfreebsd kfreebsd_loadenv kfreebsd_module kfreebsd_module_elf knetbsd knetbsd_module knetbsd_module_elf kopenbsd kopenbsd_ramdisk legacy_check_password legacy_configfile legacy_initrd legacy_initrd_nounzip legacy_kernel legacy_password legacy_source linux linux16 list_env load_env loadfont loopback ls lsacpi lsapm lsfonts lsmmap lsmod lspci md5sum menuentry module module2 multiboot multiboot2 normal normal_exit ntldr outb outl outw parttool password password_pbkdf2 play probe pxe_unload read read_byte read_dword read_word reboot regexp return rmmod save_env search search.file search.fs_label search.fs_uuid sendkey serial set setparams setpci sha1sum sha256sum sha512sum shift sleep source submenu terminal_input terminal_output terminfo test test_blockarg testload true unset usb vbeinfo vbetest videoinfo videotest write_byte write_dword write_word xnu_devprop_load xnu_kernel xnu_kernel64 xnu_kext xnu_kextdir xnu_mkext xnu_ramdisk xnu_resume xnu_splash xnu_uuid zfs-bootfs zfsinfo
GRUB自带了很多mod模块,一般存储在/boot的某个目录并以.mod结尾,通常GRUB自动加载基本模块。
grub> lsmod
Name Ref Count Dependencies
minicmd 1
normal 1 terminal,boot,crypto,gfxterm,extcmd
gzio 0
terminal 2
boot 2
crypto 2
gfxterm 2 video,font,bitmap_scale,bitmap,extcmd
font 3 video,bufio
video 7
bufio 4
bitmap_scale 3 bitmap
bitmap 7
extcmd 5
part_msdos 1
ext2 1 fshelp
fshelp 2
biosdisk 1
特殊情况下,则需要手动加载,比如启动时最需要的文件系统和显示模块等。
grub> insmod ext2
GRUB加载模块之后,如果模块兼容,设备上的外设能够自动被识别到:
grub> lspci
00:00.0 8086:0150 [0600] Host Bridge
00:01.0 8086:0151 [0604] PCI-PCI Bridge
00:02.0 8086:0152 [0300] VGA Controller
00:14.0 8086:1e31 [0c03] USB Controller [PI 30]
00:1a.0 8086:1e2d [0c03] USB Controller [PI 20]
00:1c.0 8086:1e10 [0604] PCI-PCI Bridge
00:1d.0 8086:1e26 [0c03] USB Controller [PI 20]
00:1e.0 8086:244e [0604] PCI-PCI Bridge [PI 01]
00:1f.0 8086:1e47 [0601] ISA Bridge
00:1f.2 8086:1e02 [0106] SATA Controller [PI 01]
00:1f.3 8086:1e22 [0c05] Serial Bus Controller
00:1f.6 8086:1e24 [1180] Unknown Data Input System
01:00.0 177d:0091 [0b30] MIPS Processor
07:00.0 8086:150f [0200] Ethernet Controller
使用ls命令查看设备上所有可用的磁盘分区列表:
grub> ls
(hd0) (hd0,msdos2) (hd0,msdos1) (hd1) (hd1,msdos1) (hd2) (hd2,msdos3) (hd2,msdos2) (hd2,msdos1)
启动分区存储linux系统启动所需的linux内核和initrd文件。大型设备可能由于可用性需要,通常存在不止一个启动分区,比如说2个跟文件系统分区;一个紧急恢复系统分区。多个启动分区也就对应多个linux系统,如果想加载指定的操作系统,就要设置对应的操作系统内核所在的启动分区。
以设置最后一块磁盘的第一个分区(hd2,msdos1)为启动分区:
grub> set root=(hd2,msdos1)
通过前文设置启动分区之后,在根目录下执行tab命令就能够看到分区下都有哪些文件可以使用,加载对应的内核文件即可:
grub> linux /
Possible files are:
lost+found/ System.map-2.6.32-220.el6.x86_64 config-2.6.32-220.el6.x86_64 efi/ initramfs-2.6.32-220.el6.x86_64.img initrd-2.6.32-220.el6.x86_64kdump.img symvers-2.6.32-220.el6.x86_64.gz vmlinuz-2.6.32-220.el6.x86_64 boot/
grub> linux /vmlinuz-2.6.32-220.el6.x86_64
初始 RAM 磁盘(initrd)是在实际根文件系统可用之前挂载到系统中的一个初始根文件系统。initrd 与内核绑定在一起,并作为内核引导过程的一部分进行加载。内核然后会将这个 initrd 文件作为其两阶段引导过程的一部分来加载模块,这样才能稍后使用真正的文件系统,并挂载实际的根文件系统。initrd 中包含了实现这个目标所需要的目录和可执行程序的最小集合,例如将内核模块加载到内核中所使用的 insmod 工具。在桌面或服务器 Linux 系统中,initrd 是一个临时的文件系统,用作真实文件系统加载的一个桥梁。在没有存储设备的嵌入式系统中,initrd 是永久的根文件系统。
grub> initrd /initramfs-2.6.32-220.el6.x86_64.img
GRUB中boot用来执行最后的内核加载和启动的过程:
grub> boot
default=0
timeout=3
menuentry "Linux OS" {
set root=(hd0,1)
linux /vmlinuz-2.6.32-220.el6.x86_64 root=/dev/sdb1 console=tty1 console=ttyS1,115200n8
initrd /initramfs-2.6.32-220.el6.x86_64.img
}