您当前的位置:首页 > 计算机 > 系统应用 > 操作系统

MBR/BOOT和GRUB三者关系总结(系统启动过程)

时间:03-15来源:作者:点击数:

MBR是硬盘上的一个扇区,包含三部分内容(引导程序、分区表及分隔标识,MBR总计512字节;其中引导程序最多占446个字节);为什么需要这个MBR,主要是因为BIOS太小,功能有限。当系统加电,bios自检后,就会将MBR Load进内存。也就意味着引导程序被激活,分区表信息已经加载到内存,同时也意味着对系统的控制权从bios过渡到GRUB.GRUB是GRand Unified Bootloader的缩写,它是一个多重操作系统启动管理器。用来引导不同系统。

GRUB是一个系统引导程序,分为两个阶段,

第一阶段它保存在MBR中.用汇编语言编写,也就是MBR中的引导程序部分。①基本的硬件设备初始化(屏蔽所有的中断、关闭处理器内部指令/数据cache 等)。②为加载 Bootloader 的Stage2 准备空间。③如果是从某个固态存储媒质中,则拷贝 Bootloader 的stage2 到RAM 空间中。④设置好堆栈。⑤跳转到 stage2 的C 程序入口点。

GRUB引导程序的第二阶段,通常用C语言编写,这个阶段的任务有: ①初始化本阶段要使用到的硬件设备。②检测系统内存映射。③将kernel 映像和根文件系统映像从flash 上读到RAM 空间中。④为内核设置启动参数⑤调用内核。

它通常保存在/boot/grub/中。 当我们启动系统进入GRUB界面时,会看到有选择信息,如果我们自己编译了系统内核的话,你可以选择从某个内核启动。同时要注意的是GRUB的配置文件和内核在/boot分区。从前面分析我们可以看出,/BOOT和MBR不存在包含关系。GRUB第一阶段需要去MBR中去读引导程序,GRUB第二阶段需要到/boot分区读系统内核和配置文件。

BOIS >>MBR (第一个磁盘的第一个分区)>>在MBR中读取grub引导程序

补充:

计算机运行起来后,一切都很正常,并且很多理论你都可以在很多资料上学到,然而,一切是如何开始的呢?开始意味着诞生,生活是乏味的,然而诞生一个生命却是需要十月怀胎的,一个生命总是在充满激情与畅想的十月之后诞生的,计算机的运行也不例外,在计算机中,对于运行而言最重要的东西其实不是操作系统,也不是应用程序,而是BIOS或者类似的东西,它里面记录着一张拓扑图,这张拓扑图描述了计算机的硬件是如何连接在一起的-比如网卡芯片在第几条pci总线上,以及各个硬件是如何配置的-比如时钟的值或者启动顺序,有了这张图,以后的操作系统才可以在这张图上谱写绚美的华章。在操作系统中,经常要处理与中断相关的信息, 每个设备的中断号从哪里来?这些都需要bios对信息的提供,计算机的启动程序存放在哪里?这些信息也需要bios的提供。比方说从ide的第一个磁盘启动操作系统的话,那么系统自然会把执行权力交给ide第一块磁盘中存放的某个程序。为了不同磁盘对不同操作系统的标准化,每个启动磁盘的前512字节被称作MBR。

mbr中存放了启动程序和该磁盘的分区表,分区表一共描述了4个分区,其中一个分区为可启动分区,mbr中的启动程序的任务就是在分区表中找到这个启动分区,然后将执行权力交给启动分区的引导程序,至于这个引导程序如何做,那就交给操作系统的设计者来完成了,可以直接启动操作系统,也可以在启动操作系统前完成一些别的工作。以上就是标准化的操作系统自举的过程,然而为何必须这么做呢?因为第一,如果不是通过用户的设置,计算机不知道系统存储在哪个外部存储设备上,因此有了bios的启动顺序;第二,即使计算机知道了从第一块磁盘启动,由于磁盘可以有很多分区,它也不知道操作系统在哪个分区,因此就有了磁盘分区表中必须有一个启动分区。

就是因为计算机太傻,有了上述的两个“不知道”,所以如果解决了这两个不知道,那么就不用在计算机内部设计这么多复杂的所谓的“智能化”了,bios已经解决了第一个计算机不知道的问题,而lilo/grub等bootloader解决了第二个不知道的问题,因此自从有了grub之后,启动操作系统也成了可配置的了,和在bios中配置从特定设备启动计算机一样,在grub中可以配置在哪个磁盘分区启动哪个操作系统,因此grub根本不需要磁盘分区的active标志,一切全部都由用户的配置搞定,之所以拥有分区的active标志,那纯粹是为了操作系统自举时的自动判断启动分区所在时使用。自从有了grub,大家可以放弃很多概念了,比如启动分区之类的。

说实话,grub等bootlaoder就是一个mini OS,它的作用就是启动另一个real OS,grub的实现比简单的执行mbr的代码,判断哪个分区是启动分区,然后跳转到启动分区这种“自动化的配置”要复杂,这个复杂性主要表现在这个bootloader是可以配置的。如此复杂的代码不可能仅仅占据446字节(512-分区表)的空间,于是grub采用了“跳蛙”战术,从最简单的mbr中的代码加载其后的更大的一点的代码从而可以识别“文件系统”,然后跳转到具体的“文件系统”中,执行grub命令,加载存在于具体“文件系统”中的内核和内存盘,最终启动linux操作系统(启动windows等不直接支持grub的操作,需要显式跳转到windows的启动分区来完成启动)。

以linux为例,如果启动到了initrd,那么此时肯定已经完成了内核的加载,可以说一个系统已经完全启动完成了,余下来的只是“根”的挂载问题了,对于liveCD之类的系统,到此步就完成了,因此我们的讨论也仅到此步。那么此时的linux还会“记得”它是从那块磁盘的哪个分区加载的吗?答案是不!因为grub的kernel和initrd命令将内核和内存盘从具体的“文件系统”加载到内存,只要完成了此步,内存中就已经有了系统运行的全部信息,此时将所有的磁盘拔下,内核还是会从解压开始到达initrd的执行的,毕竟数据和代码都在内存中,此时内核仅仅是内存中的内核,它是一个全新的执行体,并不知道grub的任何信息,也不知道是谁将它引导起来的(grub和linux内核的解耦合),内核将丢失所有grub所知道的硬件信息,当然包括磁盘信息,如想知道此时内存中的内核和initrd是从哪一块磁盘的哪一个分区被加载到内存的,不得不从sysfs的block目录中得到更详细的信息,然后遍历所有的磁盘,寻找特征从而加以判断。

如果我事先做好了一个dom盘,cf卡或者磁盘,然后事后可能将之插入到不同的机器上,鉴于每台机器的ide口的硬连线可能顺序不同,比如在pc1上的ide口是hda,在pc2上或许就是hdb,如果我将grub的配置文件写成root=/dev/hda1那么在pc2上可能就无法启动,如何能做到自适应启动呢?在仅有一块块设备(磁盘)的情况下,我可以在initrd的/init脚本中挂载sysfs在/sys,然后再在/sys/block/下查找唯一的磁盘,然后直接挂载之,然而如果不仅仅有一块磁盘呢?那么一个可选的方法就是在启动磁盘的/下创建一个文件abc(确保唯一性),然后分别挂载所有的/sys/block下的磁盘,查找/下是否有一个abc的文件...仅此...

启动第一步--加载BIOS

当你打开计算机电源,计算机会首先加载BIOS信息,BIOS信息是如此的重要,以至于计算机必须在最开始就找到它。这是因为BIOS中包含了CPU的相关信息、设备启动顺序信息、硬盘信息、内存信息、时钟信息、PnP特性等等。在此之后,计算机心里就有谱了,知道应该去读取哪个硬件设备了。

启动第二步--读取MBR

众所周知,硬盘上第0磁道第一个扇区被称为MBR,也就是Master Boot Record,即主引导记录,它的大小是512字节,别看地方不大,可里面却存放了预启动信息、分区表信息。

系统找到BIOS所指定的硬盘的MBR后,就会将其复制到0×7c00地址所在的物理内存中。其实被复制到物理内存的内容就是Boot Loader,而具体到你的电脑,那就是lilo或者grub了。

启动第三步--Boot Loader

Boot Loader 就是在操作系统内核运行之前运行的一段小程序。通过这段小程序,我们可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核做好一切准备。

Boot Loader有若干种,其中Grub、Lilo和spfdisk是常见的Loader。

我们以Grub为例来讲解吧,毕竟用lilo和spfdisk的人并不多。

系统读取内存中的grub配置信息(一般为menu.lst或grub.lst),并依照此配置信息来启动不同的操作系统。

启动第四步--加载内核

根据grub设定的内核映像所在路径,系统读取内存映像,并进行解压缩操作。此时,屏幕一般会输出“Uncompressing Linux”的提示。当解压缩内核完成后,屏幕输出“OK, booting the kernel”。

系统将解压后的内核放置在内存之中,并调用start_kernel()函数来启动一系列的初始化函数并初始化各种设备,完成Linux核心环境的建立。至此,Linux内核已经建立起来了,基于Linux的程序应该可以正常运行了。

启动第五步--用户层init依据inittab文件来设定运行等级

内核被加载后,第一个运行的程序便是/sbin/init,该文件会读取/etc/inittab文件,并依据此文件来进行初始化工作。

其实/etc/inittab文件最主要的作用就是设定Linux的运行等级,其设定形式是“:id:5:initdefault:”,这就表明Linux需要运行在等级5上。Linux的运行等级设定如下:

0:关机

1:单用户模式

2:无网络支持的多用户模式

3:有网络支持的多用户模式

4:保留,未使用

5:有网络支持有X-Window支持的多用户模式

6:重新引导系统,即重启

关于/etc/inittab文件的学问,其实还有很多

启动第六步--init进程执行rc.sysinit

在设定了运行等级后,Linux系统执行的第一个用户层文件就是/etc/rc.d/rc.sysinit脚本程序,它做的工作非常多,包括设定PATH、设定网络配置(/etc/sysconfig/network)、启动swap分区、设定/proc等等。如果你有兴趣,可以到/etc/rc.d中查看一下rc.sysinit文件,里面的脚本够你看几天的

启动第七步--启动内核模块

具体是依据/etc/modules.conf文件或/etc/modules.d目录下的文件来装载内核模块。

启动第八步--执行不同运行级别的脚本程序

根据运行级别的不同,系统会运行rc0.d到rc6.d中的相应的脚本程序,来完成相应的初始化工作和启动相应的服务。

启动第九步--执行/etc/rc.d/rc.local

你如果打开了此文件,里面有一句话,读过之后,你就会对此命令的作用一目了然:

# This script will be executed *after* all the other init scripts.

# You can put your own initialization stuff in here if you don’t

# want to do the full Sys V style init stuff.

rc.local就是在一切初始化工作后,Linux留给用户进行个性化的地方。你可以把你想设置和启动的东西放到这里。

启动第十步--执行/bin/login程序,进入登录状态

此时,系统已经进入到了等待用户输入username和password的时候了,你已经可以用自己的帐号登入系统了。:)

===

漫长的启动过程结束了,一切都清静了…

其实在这背后,还有着更加复杂的底层函数调用,等待着你去研究…本文就算抛砖引玉了:)

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门