这几天对于操作系统是如何引导启动的特征的感兴趣,已经到了不能自拔的状态了,所以索性好好了解一下;
前面已经说过了,MBR对于系统启动的重要性,这是不多啰嗦; 现在介绍一个 grub ,启动管理器,它可以用于引导不同的系统;
grub 是一个怎么样的引导原理?
通过我的实验,我得到的结论就是: 整个grub启动管理器其实也算是有点大的,引导扇区里是放不开的; 所以,grub会往引导扇区(可以是MBR, 也可以是每一个分区里面的引导扇区)里面写入部分内容,对于剩余的部分,它会写入到我们的硬盘分区里面的;在启动时,首先运行引导扇区里的程序, 然后在运行硬盘分区里的程序,最后引导操作系统;
对于引导扇区里的程序是如何找到硬盘分区里的程序与配置的,这个就是细节方面的问题了,我们可以忽略;不过我也是一个好学习的人,我也查了查相关的资料,有的解释如下:
来自:作者:js li
链接:https://www.zhihu.com/question/27652991/answer/37500373
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。grub的话,肯定是要在mbr里写东西的,但446字节的机器码也干不了太多东西,只是负责把后续的内容加载到内存在执行而已。这个写到mbr的是stage1,它加载的是写在mbr之后62个扇区中的stage1.5(因为过去磁盘是按磁道还划分分区的,一个碰道63个扇区,因为mbr占据了第一个磁道的第一个扇区,所以第一个分区只能从第二个磁道开始,这样在mbr和第一个分区之间就留下了62个扇区的空间,62*512byte=31KB)。
mbr之前说了容量太小没法放下识别文件系统的代码,只能以计算扇区绝对偏移的方法加载stage1.5,但31KB的stage1.5就足够了(但基本也只够一种类型的文件系统,所以stage1.5是有好几个,分别对应ext4,xfs等等,在grub安装时根据需要写入,随便一提,正是因为GPT分区表占用了后62个扇区的相当一部分位置,导致空间不够写下stage1.5,所以需要额外分出一个非常小的分区来存放)。 (我的备注:我在写grub时,没有设置是ext4,还是xfs, 应该是它自动识别的吧)
stage1.5可以识别文件系统,然后根据安装时硬写到里面的系统路径(hexdump可以看到)找到stage2,然后这个stage2才是真正负责干活的,它会读取grub.cfg并生成启动菜单,然后根据你的选择加载内核并把执行权限转过去,完成启动。
实验部分:
先跟着实验走一遍,然后就会更容易明白grub是如何引导的,来,先折腾起来:
我使用的grub版本分别为 grub-0.97 和 grub-2.02;
grub-0.97 的使用:
第一步:我们下载 grub-0.97这个工具,并安装到 linux系统上
(注意:这里说的安装是指的 把这个 grub-0.97 工具安装到 linux 上,而不是把 grub-0.97的启动管理器安装到 硬盘分区上;我们需要使用grub-0.97 这个工具来安装 grub-0.97 启动管理器)
方法1:在 linux 上 使用 apt-get install grub 下载下来的为就是 grub-0.97版本的,所以直接 apt-get install grub 就下载下来了;
方法2:当然也可以下载源码,自己编译(下载地址:ftp://alpha.gnu.org/gnu/grub/):别忘了给 root 权限:
// 假设应该下载完毕,,位置目录 grub 下: tar xzvf grub-0.97.tar,gz ./configure --prefix=/usr // prefix 指定了安装的位置,当然也可以放在其它地方,不过需要添加一下环境变量, // 如果不过添加环境变量,就到安装的目录下去运行也可以; make make install
第二步:安装grub 引导管理器到硬盘分区:
方法1:是通过命令一步步的安装,输入 grub 会出来 grub的交互窗口如下图,这时可以输入命令进行安装; 至于命令吧,我没有研究啊,用第二个方法方便;
方法2: 用自带的 grub-install 脚本安装: 这个脚本其实也是调用 grub 的命令进行安装的:
首先 使用help 来看看grub的用法,输入 grub-install –help:
所以,我们知道了 grub-install 的用法啦.我们仅仅使用下面的命令格式就可以了,其它的就不用管了:
sudo grub-install --root-directory=DIR install_device // DIR指的是grub的安装到硬盘的那一部分的目录位置;其实这个不重要,写到哪里都可以,反正 grub 的第一部分都可以找到的;只要你记住就可以了,因为可以在里面加入配置文件的;
// 不过有一点要求:那就是把交叉硬盘,即不能把grub的第一部分与第二部分写在不同的硬盘上,我试过,会报错的;
// install_device 表示了安装到引导扇区的那一部分的到底的安装到哪一个引导扇区; // 例如:一块硬盘为sda, 如果 install_device 为 /dev/sda,则表示安装到了这个硬盘的MBR上; // 如果 install_device 为 /dev/sda1,则表示安装到了这个硬盘的第一个主分区的引导扇区上; // 当然如果安装到第MBR上, grub启动管理器可以正常运行,如果安装到分区的引导扇区上,则需要使用到 chainloader(下面会说到)
安装完成以后,我们在 sdb1的分区下面应有了一个 /boot/grub/ 目录了;里面有相关的内容;
举个两个例子:
我给虚拟机加了一块硬盘sdb,并且已经分区、格式化完成了,如下:
例子1:把 grub的 引导程序的第一部分写到硬盘的MBR上, 至于grub的剩余部分安装到哪,都行,我就安装到第一个分区里吧,过程如下:(我要先创建一个空目录 sdb1,然后把硬盘的第一个分区挂载到上面)
这时,开机把启动项选择从硬盘 sdb启动, 就会出现 grub> 窗口了,如下:(由于sdb硬盘上 grub,并没有配置信息: menu.lst,所以它自己找不到sda硬盘上的系统上,所以需要进行手动引导,见下面)
例子2:把 grub的 引导程序的第一部分写到硬盘第一分区的引导扇区上, 至于grub的剩余部分同样的安装到哪,都行,我就安装到第一个分区里吧,过程如下:(我要先创建一个空目录 sdb1,然后把硬盘的第一个分区挂载到上面)
方法与上面相同:只需要把sdb 改为 sdb1就可以了;
补充:(这一小段来自:http://blog.csdn.net/zzqhost/article/details/5935317)
grub-install 是一个脚本,它完成以下任务:
* 调用 grub-mkdevicemap 创建设备映像文件 /boot/grub/device.map
* 复制 *.mod *.lst *.img 文件到 /boot/grub/
* 调用 grub-probe 自动侦测文件系统类型
* 调用 grub-mkimage 生成grub2内核文件 /boot/grub/core.img
* 调用 grub-setup 安装引导记录到mbr或分区-
第三步:grub> 命令窗口下如何手动启动 linux 系统:
由于sdb硬盘上 grub,并没有配置信息: menu.lst,所以它自己找不到sda硬盘上的系统上,所以进行手动引导:
说明: 1.在 grub-0.97中,会把硬盘识别为 hd0,hd1,hd2, ……; 分区也是从0标志开始的,如第一分区(hd0,0), 第二分区(hd0,1),……;
2. grub 会把启动盘作为 hd0盘,其它盘为hd1, hd2等;
3. 记得用 tab 补全;
命令如下:
解释: 1. 第一行 root (hd1,0), 表示设置一个 linux 系统的 /boot 目录的分区,在这个 /boot 目录下有 内核文件与启动的镜像文件;又由于 这个分区是 grub 看到的,所以用grub的格式表示,那为什么为(dh1,0)呢??因为现在的启动盘为 sdb,而linux的系统在sda的第一个分区上,所以为(dh1,0); 如果省略这个 root (hd1,0) 也可以,后面找内核与镜像文件时再指明也行,只是会麻烦一些;
2. 第二行的命令是加核 linux 的内核文件, 对于后面的 root=/dev/sda1是什么?? 它指明了 linux 系统的 / 目录所在的分区,因为需要把很多东西mount到 / 目录下的目录名字下; 这个分区的路径是 linux 系统看到的,所以为 /dev/sda1;
3. 加载映像文件;(什么是initrd.img,百度或google)
4. 启动;
第四步: 配置 grub-0.97的配置文件,让它自动引导:
在 grub-0.97的 配置文件名字为:menu.lst 文件;至于配置文件的内容的书写方式,不多说,网上有很多,再说 现在都用grub2了,它的配置文件变了,所以研究也没有用了;我怎么做的呢?我先用 linux 上的grub-0.97 来自动自成一下 配置文件(命令:udpdate-grub),然后把它复制到 sdb1下的 /boot/grub/ 目录下(这个是我们上面生成的), 然后修改一下: 添加了一行命令: root (hd1,0) :
修改前:
修改后:
此时,我们重新从 硬盘 sdb里启动电脑,就可以启动了:
完成;
grub-2.02 的使用:
整个过程与grub-0.97 是相同的,说说不一样的地方 :
1. grub-2.02 可以在这里下载:ftp://ftp.gnu.org/gnu/grub/ 或 ftp://alpha.gnu.org/gnu/grub/;
或者: ap-get install grub2-common;
2. grub-2.02支持更多的命令;
3. grub-2.02的 grub-install 的参数不一样了,同样可以通过 grub-install –help查看,部分如下:
在使用时,这么用:
sudo grub-install --boot-directory=DIR install_device // 例如: sudo grub-install --boot-directory=/sdb1/ /dev/sdb // 它指的是 boot的目录 , 而不是root的目录了;
4. 在 grub-2.02中,会把硬盘识别为 hd0,hd1,hd2, ……; 而分区也是从msdos1标志开始的,如第一分区(hd0,msdos1), 第二分区(hd0,msdos2),……;
5. 在grub-2.02中的配置文件变成了 grub.cfg;
6. 当我把 grub-2.02安装到 sdb的MBR时, 把 linux系统下的 grub.cfg 文件复制到 sdb1分区上的 /grub/ 目录下时, 修改如下:
把 grub.cfg 里面的 hd0 全部替换为 hd1; 最后,在sdb硬盘启动时, sda上的 linux 系统启动成功;
7. 我发现使用在grub-2.02里,使用grub-install 写入到分区的引导记录时,会出问题,而使用grub-0.97则不会再现问题;
8.grub-2.02的命令有所不同:
set root=(hd1,msdos1) linux /boot/ vm**** boot=/dev/sda1 initrd /boot/initrd.img*** boot
当把grub 没有安装到硬盘的 MBR里面,而是安装到了 第一分区,或第二分区时,怎么办?
使用 chainloader 命令( 它属于 grub的命令),它可以调用另一个启动器,如:在grub中,输入命令例如:
root (hd0, 0) // 为安装grub 的分区,这是为第一分区;
chainloader +1 // 将指定的文件作为一个链式装载程序载入。为了获取在一个指定分区第一 扇区内的文件,使用+1作为文件名。
boot
这时,就会从硬盘的第一分区进行启动了;
完;
另外:可以看看相关的:GRUB(简体中文);