「Linux Boot Process and Shutdown」- Boot loader Stage 2(GRUB Boot loader)

显示可选择菜单

然后,启动加载器会根据配置文件,向用户显示可选择菜单,来提供可选择的启动项。

值得注意的是,虽然该菜单是 /boot/grub/grub.cfg 定义的,但是 GRUB 在显示该菜单的时候,并不是读取 /boot/grub/grub.cfg 文件。

用户选择启动项

概述:当用户选择启动项后,根据启动项配置,Bootloader 会从磁盘加载配置的 kernel、initramfs 镜像,并载入内存中。

如下截取自 /boot/grub/grub.cfg 配置,是第一个菜单项的内容:

menuentry 'Ubuntu' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-02a38d2f-1340-452f-ba82-79ffbe8498ce' {
        recordfail
        load_video
        gfxmode $linux_gfx_mode
        insmod gzio
        if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi
        insmod part_gpt
        insmod ext2
        set root='hd0,gpt2'
        if [ x$feature_platform_search_hint = xy ]; then
          search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt2 --hint-efi=hd0,gpt2 --hint-baremetal=ahci0,gpt2  f2999e53-cb52-46ab-b419-c27f4cdd1134
        else
          search --no-floppy --fs-uuid --set=root f2999e53-cb52-46ab-b419-c27f4cdd1134
        fi
        linux   /vmlinuz-5.4.0-84-generic root=/dev/mapper/ubuntu--vg-ubuntu--lv ro  maybe-ubiquity
        initrd  /initrd.img-5.4.0-84-generic
}

当用户选择该菜单后,GRUB 将执行该菜单中定义内容(即花括号内的指令)。

在这些指令中,对启动起关键作用的指令有四类:
1)insmod xxx
2)set root=’hd0,gpt2′
3)linux
4)initrd

insmod xxxxxx

该指令用于加载 GRUB 模块,这些模块使得 GRUB 能够识别 分区格式、文件系统、逻辑卷 等等。

值得注意的是,虽然我们看到 /boot 目录下保存很多 GRUB 启动相关的文件,但是在 GRUB 运行时并没有直接读取这些文件。而实际情况是,这些文件被 grub-install 安装(复制)到磁盘分区前的一段空隙中,GRUB 将读取被复制到这段空隙的那些配置文件。

set root=’hd0,gpt2′

当前系统中可能存在多个磁盘,该指令指定需要使用的磁盘,后续将从该磁盘中读取相关文件。

通过该指令(从哪个磁盘读取文件),结合前面的 insmod ext2 使得 GRUB 能够识别 Ext 文件系统(该磁盘使用什么格式),GRUB 现在能够从文件系统中读取 Linux Kernel 文件,以及其他相关配置文件。

这是个重要的时刻:现在 GRUB 已能够识别文件系统,并且能够从文件系统中读取文件。

linux /vmlinuz…

vmlinuz 是 Linux Kernel 可执行文件的名称,是个压缩的 Linux Kernel,并且可引导:
1)可引导,意味着它能够将操作系统加载到内存中;
2)vmlinuz 不仅是个压缩的镜像文件,它还内置 gzip 解压代码;
3)注意与 vmlinux 区分,vmlinux 是产生 vmlinuz 的中间步骤;

linux 指令负责从文件加载 Linux 内核映像,并加载到内存中。该行的其余部,将分作为内核命令行参数,逐字传递。

当使用 linux 命令后,必须重新加载任何 initrd

initrd /initrd…

按顺序,为 Linux Kernel 加载所有的 initrd(initial ramdisk),并在内存中的 Linux Setup Area 中设置适当的参数。

该指令只能在运行 linux 命令的后面使用。

参考文献

GNU GRUB Manual 2.06: linux
GNU GRUB Manual 2.06: initrd
http://www.linfo.org/vmlinuz.html