方永、南天紫云

道亦有道

grub启动过程分析
作者 vinoca 發布於 2011年10月29日

翻linuxsir的精华贴,看到“GRUB源码分析”一文,其中几位前辈谈笑于源码、原理之间,颇感现在世风日下,学习气氛大不如前,耐心看完后尚觉许多不足,一如linuxsir坛子里的语调,太文邹邹,而且关键之处并没有讲到。遂花了点时间读了读grub4dos及grub2的代码,以及非常非常好的一篇文章——grub2的info手册。

grub4dos启动分三个阶段,stage1、stage1.5、stage2,stage1在MBR中,stage1.5在“MBR gap”中,stage2在文件系统中。MBR就是磁盘的最开始的512个字节,stage1写在了MBR的前446个字节中,剩下的60来个字节还要放分区表。stage1判断磁盘处于CHS或者LBR模式并运行相应代码,将stage1.5装载到内存并运行stage1.5。stage1.5在“MBR gap”中,也就是MBR与第一个分区之间的那点儿间隙,因为现在的磁盘空间都很大,为了提高性能,好的分区工具默认都是兆字节以上对齐的,所以这个间隙常常在1M以上,但怕的就是例外,所以stage1.5一般保持在31Kb以下。stage1.5稍微大些,所以能够识别一些文件系统,grub和grub4dos或许在这里对文件系统的处理的种类和数目不同。stage2在文件系统中,stage1.5能够访问文件系统并找到stage2的文件并运行,stage2加载配置文件并给出菜单选项或者mini shell。

分三个阶段,是由于代码储存空间的限制,MBR就那么点字节,现代的编译器生成的helloWorld也都在1K以上,所以“MBR gap”的空间就显得非常宝贵和重要,但是现有的文件系统种类很多,即使DOS中的FAT驱动,也有好几K,31K对于驱动所有的文件系统来说又显得非常狭小了。stage1.5只是加载少量文件系统的驱动,避免代码膨胀。

这里突显了供需矛盾是如何的尖锐。

grub的开发者们也在思考怎么解决这个问题。于是grub2就诞生了。grub2是重写的,相比原先的grub,最重要的变化就是模块化。而且更加健壮了。模块化不仅仅是能看到的那些grub目录中的.mod文件,更重要的地方在于grub2的安装过程。

新的grub启动分两个阶段,boot.img、cdboot.img、pexboot.img这些是一个阶段,然后是core.img这个阶段,和原来的grub相比较,boot.img阶段对应于stage1阶段,core.img对应于stage1.5阶段,因为它们储存的位置是一样的(当然,core.img也可以安装在其它地方),但是,新的grub在core.img阶段之后,基本的功能已经有了,即使所有的分区全部格式化了,还能抛出一个mini shell。这就是相对健壮的原因。

新的grub在core.img这个阶段完成之后,根据grub的环境变量prefix和root找到.mod模块文件,然后加载normal模块,这个模块会加载配置文件,最终看到了grub的菜单选项。

prefix和root环境变量是硬编码写入到core.img里面的,其实就是grub-mkimage及grub-install等安装工具将一个配置文件生成并打包进core.img镜像文件中。这些安装工具会检测文件系统等信息,生成特定的core.img并默认写到“MBR gap”中,因此有时重新分区后会出现一个”grub rescue”的shell,只要根文件系统及.mod文件还在,输入下面的命令:

set # 查看当前的环境变量
ls # 查看当前的分区情况
set prefix=xxx # 设置perfix变量默认是/boot/grub
set root=xxx # 设置root变量根文件系统所有分区
inmod normal # 加载normal这个模块
normal # 运行normal命令,这个命令存在于normal模块中

就可以恢复整个系统,系统启动后重新安装一下grub就可以了。

新的grub的stage2,由于模块存在于文件系统中且是一系列文件,而且core.img安装时只集成模块文件存在的那个分区的文件系统的驱动,所以相比grub4dos将需要的所有代码放在GRLDR单个文件中不太灵活,而且grub4dos的安装只是将固定的字节流写入,更为简便。所以可以将GRLDR复制到多个分区根目录底下,格式化其中一个分区并不会影响grub4dos的启动,另外,grub4dos可引导各种镜像文件包括光盘镜像文件,而且网上学习资源充足,学习成本比较低,这是许多人仍在用旧的grub的一个原因。我非常喜欢grub4dos的光盘引导功能,开虚拟机速度慢,重要的是不能如实反应真实的情况。

新的grub不仅仅设计理念做了重要改变,而且更像个微型系统,其本身提供变量、分支循环等语言的基本结构,语法接近于linux shell语言。添加了很多新的特性,提供了lua模块,为grub功能的扩展提供了极好的接口,png、jpg图像可直接作为背景,这个很喜欢;可定义主题,提供了各种控件,如标签、进度条、滚动条等等,甚至有容器,具有极高的可定制性,语法也契合主流。光盘的启动界面是很重要的,第一印象嘛,grub的主题定制功能提供了做出功能强大、界面绚丽的机制。

目前grub的开发十分的活跃,而且release版已经非常地稳定,我在几台电脑上安装了新的grub,没有出现过因为grub自身的bug导致启动失败的情况。