grub 学习之路
现在,是grub2的天下了呀,虽然网上关于grub2的资料不少,但很多都是就一个方面讨论的,跟着这些教程配置虽然也能够成功,但总是迷迷糊糊,不知这grub2背后到底是怎么实现的。所以决定花时间深入了解一下。在学习grub2之前,我特地去看了以下grub2的前身:grub。
所以,就有了这篇文章。作为自己的笔记,也供大家参考,因为(目前)没办法弄到grub的实践环境(缺少编译环境),一大部分都是用grub2来试。所以只是凭着个人的理解,参考grub手册和网上各位大神的博客写出这篇博客。如果诸位前辈发现有错误的地方,希望自己能抛砖引玉,得到前辈们的指点。谢谢。
一般你装完系统,grub就已经自动安装好。这就很容易造成我们不了解grub,我们平时用的grub-install,在终端的grub shell界面的setup,都只是在第一个硬盘最前端512字节(或者你所安装的系统所在的分区最前端)安装grub的boot loader主程序,而不是我们理解的安装grub这个程序。(关于安装grub这个程序,我会在下面第一点就说明)所以,实质上grub就是一个程序,而grub-install等等是这个程序的功能。甚至可以说grub是一个系统。因为它不需要其他系统提供接口就可以直接运行在计算机上。事实上,你在开机时,就是先运行grub,然后通过grub加载内核(kernel)等相关文件,到启动整个系统。注意:我们平时说的grub就是说这个stage1安装的bootloader主程序。
这个流程图是大牛M. Tim Jones在Inside Linux boot process中绘制的。其中的stage1就是在"grub>"界面用setup或者在终端直接用grub-install安装的。
第一点:安装grub这个程序 =>官方说是安装Grub system(grub 系统)
如前所述,grub是默认安装在linux等系统上的。一般来说,你不需要下载安装这个程序。但为了了解grub运行机制,我们假设我们电脑上还没有安装它,我门下面来看以下它如何安装。首先,像安装其他软件一样,我们需要下载安装包。地址:ftp://alpha.gnu.org/gnu/grub/grub-0.97.tar.gz(好像不灵了,得自己去找,或者在下面我给出)
下载之后,先把它复制到/tmp目录下,然后解压:zcat grub-0.97.tar.gz | tar xvf -
解压之后,做下面的步骤就可以完成安装了:
#cd grub-0.97
#./configure
#make install
那么上面到底安装了些什么呢?如下:grub shell(就是grub>),Multiboot checker :mbchk(多重启动检查,检查内核格式用的),相关的grub image(在/usr/lib/grub/下),还有grub说明手册(通过info grub可以查看)。目前还没将grub做成bootloader,所以此时你重启是进不了系统的。当然,我们一般不会有这种情况,如前所说,我们在装系统时已经装好了grub了。还有,这里注意一下,如果你不是用grub-install安装,而是用grub shell,那么你需要将stage1和stage2复制到/boot/grub/下
第二点:安装grub(就是运行grub程序安装 grub bootloader)
第二点的预备知识: 一 块硬盘,有一个主引导记录(即MBR)。此后硬盘最多可以分成4个主分区,也可以把其中的一个主分区变成扩展分区,进而分成若干个 逻辑分区。其中每一个分区又有自己的引导扇区,虽然名字不叫MBR,但是作用是一样的,不同的是,MBR是由BIOS自 动装载到内存中并CPU跳转过去执行的,而普通分区上的引导扇区,需要MBR中的引导程序去装载并提交控制权。grub bootloader既可以装到MBR中,也可以装到任 意分区的引导扇区上。所以一台电脑上可以装多个grub。grub1(最近grub第二代已经推出,机制改变了)由三段程序组成:stage1、stage1.5、stage2。如果你装的是grub1,可以进入/boot/grub目录看一看。
安装grub时stage1和stage2是必装的,而stage1.5是可选的。
stage1:/boot/grub中的stage1文件大小为512b,它是引导扇区中引导程序(前446字节为引导程序)的备份文件,功能是用来装载 stage1.5或stage2的。
stage1.5:因为STAGE2较大,通常都是放在一个文件系统当中的,但是STAGE1并不能识别文件系统格式,所以才需要STAGE1.5来引导位于某个文件系统当中的STAGE2
stage2:grub能让用户以选项方式将OS加载、改变参数、修改选项,这些全都是stage2程序的功能。stage2可以去获取grub.conf以及menu.lst等文件的内容。
命名规则(Naming convention)。其实可以用两个例子来说明:第一个磁盘的第一个分区这样表示:(hd0,0),第二个分区则是(hd0,1);第二个磁盘第一个 分区:(hd1,0),第二个分区则是:(hd1,1)。以此类推。也就是说磁盘和分区都是从zero开始算起的。需要注意的是,linux查找磁盘是按 照查找到的先后顺叙来排序的,而不是按照在主板上的排线顺叙来分配序号的。
注意注意注意,这个步骤安装完grub bootloader后,还是只能从grub>命令行,用自己手写命令加载系统内核或将加载权转交给其他bootloader。我们平时进入系统时就能选择的那个系统的菜单是需要配置一个叫menu.lst的文件才行的。
第二点正式开始: 装完grub 这个程序后,你可以选择利用grub程序制作各种启动盘;在mbr或者分区上的引导扇区上安装bootloader。
1.先说制作启动软盘(Creating a GRUB boot floppy):
为了创建一个启动软盘,你需要在image目录下将stage1和stage2复制出来,并且将他们写在软盘的第一和第二个块上。
命令:# cd /usr/lib/grub/i386-pc
# dd if=stage1 of=/dev/fd0 bs=512 count=1//写在软盘的第一个块
1+0 records in
1+0 records out
# dd if=stage2 of=/dev/fd0 bs=512 seek=1//写在软盘的第二个块上
153+1 records in
153+1 records out
#
注意:设备(/dev/fd0)和镜像目录可能不一样,按照你自己的情况来做。
好了,一个启动软盘就做好了。可以用它来引导你的linux系统了(不能直接引导DOS/Windows哦)。选择从它开机就可以看到一个可爱的画面:
在这个界面你可以做什么?可以引导(加载)内核启动。可以给还没有bootloader的系统(linux)安装 grub bootloader。可以将引导权转交给其他bootloader。
2.接下来我们在引导扇区上安装grub(即stage1)。安装stage1也有两(多?)种方法。据官方手册介绍,用启动盘的grub shell(即grub> )安装会比较安全。而用在终端运行的grub shell 或者 grub-install安装的话可能会由于找错硬盘或分区(mapping错误:硬盘映射错误)而导致将stage1安装在错误的扇区。
2.1 启动盘安装grub bootloader(Installing GRUB natively) 注意:用这种方法安装会擦除安装在分区上的系统的bootloader。
这种方法安装你需要做一个启动盘(例如上面做的软盘),插入电脑,重启,并从启动盘启动,如上面插图一样,你会看到一个grub> 如下:
grub> root (hd0,0) =>这个是指定你的stage1文件在哪里,一般都在/boot/grub/下。为什么指定?你要安装stage1总得告诉"grub>"stage1在哪吧?
如果不确定的话,可以这样找: grub> find /boot/grub/stage1 =>会将含有stage1的磁盘分区罗列出来,一般只有一个。
grub> setup (hd0) =>将grub bootloader安装在第一个磁盘的Master Boot Record (MBR)上
嘿嘿,如果你想安装在你系统的引导扇区(boot section)上,你可以这样:
grub>setup (hd0,0) =>第一个磁盘第一个分区的引导扇区。
setup完之后,下次重启你就可以不需要启动盘都可以出现grub>图标。也就是说,grub bootloader 已经装好了。下面,就可以利用这个画面booting(加载)内核,进入系统了。
2.2 上面用的是启动盘引导安装,这里说一下用grub-install安装。(这种方法是我们平时用得最多的,但它不一定每次成功,因为可能出现mapping 错误,一般它都会提示你检查device.map这个文件),开始吧
# grub-install /dev/hda
运行这一步发生什么呢?会默认将/usr/lib/grub/下的相关配置文件image等复制到/boot/grub/目录下,然后在第一个磁盘的mbr上安装grub bootloader。这也是为什么我说如果不用grub-install安装的话,要先将/usr/lib/grub/下的stage1等东西复制到/boot/grub/目录下。
那如果你不想将/usr/lib/grub/下的配置文件装到/boot/grub/下呢?比如我想做一个启动软(或U)盘,就需要将/usr/lib/grub/下的东西复制到软(或U)盘的grub目录下。可以这样:
# mke2fs /dev/fd0 =>将软盘格式化
# mount -t ext2 /dev/fd0 /mnt =>挂载
# grub-install --root-directory=/mnt fd0 =>--root-directory=/mnt 看,这个参数代表将/usr/lib/grub/下的文件复制到/mnt下
# umount /mnt =>这个我也不知什么意思.嘿嘿
好了,这就是利用grub-install安装grub bootloader了。到这里,肯定会发现还有一个在终端输入grub,然后出现一个grub> ;我的系统是这样的:
可以发现并没有出现grub>图标。因为我系统的grub是目前最新版的。已经将终端调用grub shell(即grub>)功能删除了。为什么删除?前面就已经提到,终端的grub shell是不安全的。它不能保证每次都能成功。官方手册里说:Note that the grub shell is an emulator。就是说grub shell只是一个模拟器。其实grub-install就是一个脚本,它通过调用grub shell来完成工作的。官方这样说:Note that grub-installis actually just a shell script and the real task is done by the grub shellgrub(see Invoking the grub shell). Therefore, you may run grub directly to install GRUB, without using grub-install. Don't do that, however, unless you are very familiar with the internals of GRUB. Installing a boot loader on a running OS may be extremely dangerous.(不想翻译了-=-)
第三点:通过grub bootloader 的grub> 加载内核等相关文件来启动 (Booting)
做完上面地步骤,你开机时,就会出现一个带有grub>的画面。也就是说,现在你可以加载启动系统了。
1.grub>kernel /boot/vmlinuz(按Tab自动补齐) root=/内核所在位置/
2.grub>initrd /boot/initrd(按Tab自动补齐)
3.grub>boot
一般是上面几个步骤,这里大致描述。更详细的话百度就有。一大堆前辈的经验。实质上很多人开机遇到grub>以为是错误,其实gurb bootloader本来就这样。
其实grub是用一致的方法引导多重引导兼任内核(Multiboot-compliant kernel)。什么是多重引导兼任内核?我去搜了一下它的含义,没有搜到。只能说一下我的理解了,多重引导兼任内核就是可以由grub直接引导的系统,像linux。而window这些不能由grub直接加载内核的,明显不是多重引导兼任内核,需要用(chainload) (如果有大神发现我理解错误,希望纠正一下,在此感激不尽)。
第四点:创建一个配置文件(Configuration)
或许你已经发现,上面的步骤下来到现在,你每次进入系统都要通过几行命令。没有谁喜欢这种方式吧?于是,grub有一个无比牛逼的方案,就是在/boot/grub/下配置一个叫menu.lst(不同系统文件名不一样)的文件,开机时就先加载这个文件,通过这个文件的配置来引导你的系统。我们平时接触的就是这个文件比较多。通过这个文件你可以配置你喜欢的东西。下面我们来简单看一下。
menu.lst文件:
default=0 <==预设开机选项,使用第 1 个开机选单 (title) timeout=5 <==若 5 秒内未动键盘,使用预设选单开机 splashimage=(hd0,0)/grub/splash.xpm.gz <==背景图示所在的档案 hiddenmenu <==读秒期间是否显示出完整的选单画面(预设隐藏) title CentOS (2.6.18-92.el5) <==第一个选单的内容 root (hd0,0) kernel /vmlinuz-2.6.18-92.el5 ro root=LABEL=/1 rhgb quiet initrd /initrd-2.6.18-92.el5.img
关键是对最后三句的理解:
root:代表的是内核文件放在哪个分区。如上则是放在第一个硬盘第一个分区(如果装系统是独立分配一个/boot,那么这里说的第一个分区就是/boot)。
这里要将/boot与根目录/区分。
kernel:kernel后面接的是内核的文件名,文件名后是参数、由于启动过程需要加载根目录(因为很多本来是内核里的配置被分化出来变成模块放在根目录里,
这样相当于简化内核体积)。因此root=LABEL=/1是指根目录所在分区。根分区放着各种系统模块,内核需要驱动他们才能完成启动系统rhgb为彩色
显示,quiet是安静模式。
initrd:由于模块被放在根目录的/lib/modules中,而usb,SATA等磁盘驱动程序通常以模块方式存在。问题是想要挂载根目录必须要取得磁盘驱动程序才能识别磁盘,
但磁盘驱动却被放
在要挂载的根目录里。这样明显进退两难。于是,要通过InitialRAM Disk(虚拟文件系统)来处理:它的文件名通常是/boot/initrd,它也能够通过bootloader
加载到内存中。然后这个文件(即/initrd-2.6.18-92.el5.img)会被解压并且在内存中仿真(虚拟)成一个根目录,这个虚拟根目录会能够提供一个加载启动过程中
所需要的各种驱动(一般是USB,SATA等驱动)的一个可执行程序。
结尾:好了,关于grub我就说这么多。但是,grub的强大之处我还没有真正全部摸索透。我学习它是因为我要学习grub2.
参考:官反手册:http://www.gnu.org/software/grub/manual/legacy/grub.html#root
转载的博客:http://tianwanjun8680.blog.163.com/blog/static/49692234201291084641655/
stage1的运行详细过程:GRUB启动分析之stage1-Bean_lee-ChinaUnix博客