熟悉系统启动流程对于我们学习Linux系统是非常有帮助的,虽然基础,但能帮助我们更加理解Linux系统的工作机制。以下将以CentOS发行版为例来介绍Linux系统的启动流程,因为在CentOS 5、CentOS 6以及CentOS 7使用的初始化程序init各不相同,虽然CentOS 6和CentOS 7都有向后兼容,但在工作机制上仍有一些差异,因此以下主要介绍CentOS 5/6系统启动流程。
CentOS的启动流程总体顺序如下(以CentOS 6为例):
POST --> Boot Sequence --> bootloader(MBR) --> Kernel --> 加载rootfs --> switchroot --> /sbin/init --> (配置文件:/etc/inittab, /etc/init/*.conf) --> 根据init配置文件设置默认运行级别 --> 运行系统初始化脚本/etc/rc.d/rc.sysinit,完成系统初始化 --> 开启或关闭用户选定的对应运行级别下所对应的服务 --> 启动终端,打印登录提示符。
注意:红色部分代表内核空间的系统启动流程,紫色部分代表用户空间的系统启动流程。
接下来逐一详解:
第一步:POST加电自检
主要实现的功能是检测各个外围硬件设备是否存在而且能够正常运行起来,实现这一自检功能的是固化在主板上的ROM(主要代表为CMOS)芯片上的BIOS(Basic Input/Output System)程序;例如BIOS会检测CPU、Memory以及I/O设备是否能够正常运行,如果是个人计算机的话可能还会检测一下显示器。只要一通电,CPU就会自动去加载ROM芯片上的BIOS程序,是这样来实现的。而检测完成之后就进行硬件设备的初始化。
第二步:Boot Sequence(选择启动设备以加载MBR)
主要实现的功能是选择要启动的硬件设备,选择了之后就可以读取这个设备上位于MBR里头的bootloader了。这一步的实现是这样的:根据BIOS中对启动顺序的设定,BIOS自己会依次扫描各个引导设备,然后第一个被扫描到具有引导程序(bootloader)的设备就被作为要启动的引导设备。
第三步:加载bootloader(MBR)
这一步实现起来的步骤比较多,前面的BIOS通过读取并执行启动设备的MBR中的bootloader,而bootloader要实现的功能就是提供一个菜单给用户,让用户去选择要启动的系统或不同的内核版本,然后把用户选择的内核版本加载至RAM中的特定空间,接着在RAM中解压、展开,而后把系统控制权移交给内核。
grub是bootloader中的一种,就grub来说,为了打破在MBR中只有446Bytes用于存放bootloader这一限制,所以这一步的实现是这样的:grub是通过分成三个阶段来实现加载内核这一功能的,这三个阶段分别是:stage1, stage1.5以及stage2。其中:
stage1:存放于MBR的前446Bytes,用于加载stage1.5阶段,目的是为了识别并驱动stage2(或者/boot)所在分区的文件系统;
stage1.5:存放于MBR之后的扇区,加载stage2所在分区的文件系统驱动,让stage1中的bootloader能识别stage2所在分区的文件系统;
stage2:存放于磁盘分区之上,具体存放于/boot/grub目录之下,主要用于加载内核文件(vmlinuz-VERSION-RELEASE)以及ramdisk这个临时根文件系统(initrd-VERSION-RELEASE.img或initramfs-VERSION-RELEASE.img)。
概述:假如要启动的是硬盘设备,首先我们的硬件平台主板BIOS必须能够识别硬盘,然后BIOS才能加载硬盘中的bootloader,而bootloader自身加载后就能够直接识别当前主机上的硬盘设备了;不过,能够识别硬盘设备不代表能够识别硬盘设备中的文件系统,因为文件系统是额外附加的一层软件组织的文件结构,所以要对接一种文件系统,就必须要有对应的能够识别和理解这种文件系统的驱动,这种驱动就称为文件系统驱动。而stage1.5就是向grub提供文件系统驱动的,这样stage1就能访问stage2及内核所在的分区(/boot)了。
演示:
[root@localhost ~]# ls -1F /boot/
config-2.6.32-642.el6.x86_64 //此版本内核被编译时选择的功能与模块配置文件;
efi/
grub/ //就是引导装载程序grub相关配置文件的目录;
initramfs-2.6.32-642.el6.x86_64.img //临时根文件系统,提供根文件系统所在分区的驱动;
initrd-2.6.32-642.el6.x86_64kdump.img
lost+found/
symvers-2.6.32-642.el6.x86_64.gz
System.map-2.6.32-642.el6.x86_64 //内核功能放置到内存地址的映射表;
vmlinuz-2.6.32-642.el6.x86_64* //就是内核文件;
[root@localhost ~]#
[root@localhost ~]#
[root@localhost ~]#
[root@localhost ~]# ls -1F /boot/grub/
device.map
e2fs_stage1_5
fat_stage1_5
ffs_stage1_5
grub.conf
iso9660_stage1_5
jfs_stage1_5
menu.lst@
minix_stage1_5
reiserfs_stage1_5
splash.xpm.gz
stage1
stage2
ufs2_stage1_5
vstafs_stage1_5
xfs_stage1_5
//可以看到stage1, 各种文件系统对应的stage1.5及stage2这几个阶段的文件都存放于此目录下;
查看grub的配置:
[root@localhost ~]# vim /boot/grub/grub.conf
default=0 //设定默认启动第一个菜单项(title);
timeout=5 //等待用户选择菜单项的时长;
splashimage=(hd0,0)/grub/splash.xpm.gz //指明菜单项的背景图片的文件路径;
hiddenmenu //是否隐藏菜单的具体内容;
title CentOS (2.6.18-398.el5) //此处为菜单项的标题;
root (hd0,0) //指定grub查找stage2及Kernel文件所在设备的分区;可理解为grub的"根";
kernel /vmlinuz-2.6.18-398.el5 ro root=/dev/VolGroup00/LogVol00 //启动的内核;
initrd /initrd-2.6.18-398.el5.img //与内核匹配的ramdisk文件;
//注意:kernel和initrd的文件路径均以grub的"根"作为起始目录,且存放于stage2所在分区上;