一篇比较老的笔记,从老博客上搬运过来的。

手头刚买了一本书,书名为《Linux操作系统之奥秘》,作者是邱世华,是台湾的一个资深工程师。当时买这本书的原因是,网上评论这本书适合已经入门但是呢对Linux又是一知半解的人。买了之后,看了一点,发现真得非常适合我,现在只是看到第二章(GRUB),但是真得受益匪浅。

之前装Linux系统,因此对GRUB也不陌生,但是顶多是停留在一些开启启动配置,又或者修复MBR等等层面,对它的原理、细节就完全不清楚了。大家都知道,MBR其实只有512字节的大小,其中bootloader更是只占了这其中的446字节,另外的分别是64字节的分区表信息(一个分区需要16字节,这也是为什么只能分4个主分区的原因)以及2字节的magic number。而GRUB的大小必然不只512字节,那么它怎么放置多出来的东西呢? 没看书之前,我估计只知道,肯定是把启动必须的代码放到MBR的前446字节,而其它的放到硬盘的其它地方,至于具体的处理方式,就....)

事实上,GRUB管理开机启动的过程分成了三个阶段,分别是stage1/stage1.5/stage2。其中,stage1主要负责BIOS和GRUB之间的交接,载入存放于各个分区中的开机文件(我的理解是,例如Linux下/boot/grub/..下面的一些文件)。这部分才是真正放在MBR中的bootloader。而后stage1.5是连接stage1和stage2之间的通道,起着过渡的作用。最后才是GRUB中真正核心的部分stage2,它可以让用户以选项的方式将操作系统加载、修改选项以及新增参数。

这些文件都是放在/boot/grub目录下:

tuantuan@~$ ls -l /boot/grub/
total 332
-rw-r--r-- 1 root root   7916 Apr 18  2010 e2fs_stage1_5
-rw-r--r-- 1 root root   7464 Apr 18  2010 fat_stage1_5
-rw-r--r-- 1 root root   6720 Apr 18  2010 ffs_stage1_5
-rw-r--r-- 1 root root   6728 Apr 18  2010 iso9660_stage1_5
-rw-r--r-- 1 root root   8180 Apr 18  2010 jfs_stage1_5
-rw-r--r-- 1 root root    512 Nov  1 12:30 mbr.txt
-rw-r--r-- 1 root root   1494 Oct 22 20:03 menu.lst
-rw-r--r-- 1 root root   6916 Apr 18  2010 minix_stage1_5
-rw-r--r-- 1 root root  32256 Nov  1 12:45 partition.img
-rw-r--r-- 1 root root   9296 Apr 18  2010 reiserfs_stage1_5
-rw-r--r-- 1 root root    512 Apr 18  2010 stage1
-rw-r--r-- 1 root root 102106 Apr 18  2010 stage2
-rw-r--r-- 1 root root 102106 Apr 18  2010 stage2_eltorito
-rw-r--r-- 1 root root   6988 Apr 18  2010 ufs2_stage1_5
-rw-r--r-- 1 root root   6340 Apr 18  2010 vstafs_stage1_5
-rw-r--r-- 1 root root   9108 Apr 18  2010 xfs_stage1_5

stage1

从上面可以看到,stage1文件的大小正好是512字节,事实上stage1文件其实就是MBR中bootloader的备份,而之所以是bootloader而不是MBR, 是因为这个文件的前446字节才是和MBR是一样的。可以自己比较下mbr和stage1:

	
tuantuan@grub$ sudo dd if=/dev/sda of=mbr bs=512 count=1
1+0 records in
1+0 records out
512 bytes (512 B) copied, 0.000103146 s, 5.0 MB/s

然后用hexdump -C命令查看下mbr和stage1两个文件的内容并比较下,确实是如此的。

stage1_5

上面可以看到stage1_5形式的文件有很多,如e2fs_stage1_5、jfs_stage1_5等等,这些都是stage1.5阶段的文件,只是每个都针对不同的文件系统格式,而e2fs_stage1_5是默认的(ext系列的文件系统?)。当stage1加载stage1.5之后,就可以识别相应的文件系统,从而可以加载stage2文件。我特地查看了下e2fs_stage1_5的内容,发现有两个地方可以看懂:

00000100  00 eb fe 4c 6f 61 64 69  6e 67 20 73 74 61 67 65  |...Loading stage|
00000110  31 2e 35 00 2e 00 0d 0a  00 47 65 6f 6d 00 52 65  |1.5......Geom.Re|
00000120  61 64 00 20 45 72 72 6f  72 00 bb 01 00 b4 0e cd  |ad.

	
00000210  02 00 30 2e 39 37 00 ff  ff ff ff 2f 62 6f 6f 74  |..0.97...../boot|
00000220  2f 67 72 75 62 2f 73 74  61 67 65 32 00 00 00 00  |/grub/stage2....|
00000230  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00

这些信息都是在stage1.5执行的过程中才会产生的信息,而stage1.5要执行,是通过stage1加载它。而Grub的做法是把stage1.5安装在硬盘最前面的32K,由stage1负责去该区域将stage1.5找出来并执行。同样地,可以将硬盘最开始的32K内容(紧跟着MBR)和 stage1.5文件作一个比较:

tuantuan@grub$ sudo dd if=/dev/sda of=partition.img skip=1 bs=512 count=63
Password:
63+0 records in
63+0 records out
32256 bytes (32 kB) copied, 0.0113796 s, 2.8 MB/s
tuantuan@grub$ hexdump -C partition.img >~/Backup/partition.txt
tuantuan@grub$ hexdump -C e2fs_stage1_5 >~/Backup/stage1_5.txt
tuantuan@grub$ vimdiff ~/Backup/partition.txt ~/Backup/stage1_5.txt

比较了一下,"几乎"是相同的,反正我这是有几处地方是不一样的。

stage2

平时开机启动的时候看到的Grub选项、信息,还有修改GRUB背景等功能都是stage2提供的,stage2会去读入/boot/grub/grub.conf或者menu.lst等配置文件。

总结

1. BIOS将控制权交给硬盘的主引导区,即MBR。
2. MBR中的bootloader(stage1)通过内置的地址加载stage1_5
3. bootloader通过stage1_5的内容,将分区中的stage2加载
4. stage2此时就可以在文件系统中将grub.conf文件加载,让用户看到选项界面。