linux开机启动流程
在系统刚启动时,系统会主动的读取BIOS加载硬件信息以及进行硬件自我检测,并根据其中设定的取得第一个开机装置的MBR(主要启动记录区)中的boot loader(开机管理程序,例如grub),然后开机管理程序就可以加载内核到内存当中解压缩并执行,此时内核就可以在内存中运行起来了。然后内核会去侦测所有硬件,如果不能识别某些硬件就需要加载硬件驱动程序来挂载根文件系统。此时内核就可以运行第一种程序init呢,等到init这只程序运行完毕后,整个linux运行环境已经准备完毕,只等待用户登入了。
可以将linux启动的流程分为如下几部:
1、读取BIOS加载硬件信息并进行自我检测
2、读取第一个可开机装置中MBR中的boot loader。
3、boot loader加载内核到内存当中解压缩并运行
4、内核侦测所有硬件信息,并加载相关硬件驱动程序来挂载根文件系统
5、运行/sbin/init这个程序,来管理用户空间的所有进程或服务
6、init这个程序运行完毕后,等待用户登入。
内核的设计风格
单内核:这种设计的内核是将许多模块直接编译到内核,因此该设计的内核容量比较大
微内核:这种设计的内核将许多的子功能设计成模块,所以当系统需要哪种功能是只需要加载相关的模块
就可以了,因此这种设计的内核容量比较小。
而在kernel中的模块叫做kernel object(ko)
在由RedHat、SuSE设计的内核中是由核心和模块组成的,该核心可以加载内核模块完成相应功能。
我们知道内核要访问根文件系统才能访问磁盘上的/sbin/init这个程序,而要想访问根文件系统,那么根文件系统必须要挂载后才可以访问,而根文件系统的挂载就需要kernel来加载硬件驱动程序来识别磁盘,从而完成根文件系统的挂载。
一般说来,我们的硬件驱动程序或者其他功能模块是放在/lib/modules/`uname -r`/kernel/目录下的,所以这个驱动程序也是存放在磁盘上的,而kernel有无法识别硬盘,那么又如何加载相应的驱动程序呢?
这时候我们就需要借助initrd这个程序了。boot loader可以将这个文件加载到内存当中解压缩仿真成一个根目录,形成一个虚拟文件系统(ramdisk)。这个虚拟文件系统中包含了开机所需要的相关模块。通常这些模块是USB、RAID、LVM、SCSI等文件系统与磁盘接口的驱动程序。因此内核就可以加载这些相关模块,释放虚拟文件系统,从而能够识别磁盘。来实际完成根文件系统的挂载。根文件系统挂载后,那么kernel就可以重新运行/sbin/init这个程序了,完成用户空间的进程初始化。
在RHEL 5中虚拟文件系统使用initrd这个程序形成的
在RHEL 6中虚拟文件系统是由initramfs形成的
从上面启动的过程中我们发现,linux的内核是通过开机管理程序(boot loader)来加载到内存中执行的。如果没有boot loader内核是无法被加载到内存当中,那么系统也就无法运行起来。所以boot loader就是整个系统启动过程中最重要的程序。目前最主流的boot loader就是grub这个程序了。
那么grub是如何完成内核加载的呢?
grub完成内核加载可分为2个阶段:
第一阶段:主要执行boot loader的主程序,这个程序放在MBR中
第二阶段:boot loader加载主要配置文件,这个配置文件为/boot/grub/grub.conf
其中主要包括的信息如下:
default=0:设定默认启动的title编号,从0开始
timeout=5:等待用户的超时时长(如果没有按键盘的话),单位为秒
splashimage=(hd0,0)/grub/splash.xmp.gz
hiddenmenu:隐藏选单菜单
title Red Hat Enterprise Linux Server (2.6.18-308.el5):内核标题或者操作系统名称,可以自由修改
root(hd0,0) #表示内核所在的设备,对于grub而言,所有类型的硬盘一律为hd,所以设备格式为
hd(#,N),其中#表示第几个硬盘,最后的N表示这个磁盘上的第几个分区。默认数字都
是从0开始的。
kernel /vmlinuz-2.6.18-308.el5 ro root=LABLE=/ rhgb quiet #内核文件所在的路径,以及传递
给内核的参数;如果/boot没有独立分区,那么此时的路径为/boot/vmlinuz*
initrd /initrd-2.6.28-308-el5.img #ramdisk文件路径
其中2.6.18-308.el5为内核版本,可以使用uname -r来查看
在/proc目录下,有一个文件叫做cmdline这个文件是用来保存kernel的参数的。
而在/pooc/目录下的每一个进程目录下,也有一个cmdline文件,这个文件是该进程启动时执行的命令。
init的配置文件为/etc/inittab
其中每一部分的信息表示的意思为:
id:3:initdefault: #表示该系统默认运行的等级为3
si::sysinit:/etc/rc.d/rc.sysinit #表示系统初始化
/etc/rc.d/rc.sysinit主要完成的任务包括如下几部分:
1、激活udev和selinux
2、根据/etc/sysctl.conf来设置内核参数
3、设置时钟
4、装载键盘映射
5、启动交换分区
6、设定主机名
7、进行根文件系统检测,并以读写方式创新挂载
8、激活RAID和LVM设备
9、启动磁盘配额
10、根据/etc/fstab来挂载其他文件系统
11、清理过期的锁和PID文件
l0:0:wait:/etc/rc.d/rc 0
l1:1:wait:/etc/rc.d/rc 1
l2:2:wait:/etc/rc.d/rc 2
l3:3:wait:/etc/rc.d/rc 3
l4:4:wait:/etc/rc.d/rc 4
l5:5:wait:/etc/rc.d/rc 5
l6:6:wait:/etc/rc.d/rc 6
#这里的每一行可以使用id:runlevels:action:process来表示
#这里的每一行都是用冒号来分成四段的,每一段表示的意思为:
第一段表示运行等级的id
第二段表示系统运行的等级
第三段表示系统在什么情况下要执行此行
第四段表示系统运作的程序,通常都是一些脚本
其中action(第三段信息)可以有这些:
initdefault:设定默认运行级别
sysinit:执行系统初始化
wait:等待级别切换到此级别时执行
respawn:一旦程序终止会立即重新启动
其中/etc/rc.d/rc 3表示在某个级别下要执行的脚本的信息,后面的数字[0-6],表示运行这个脚本时的参数,也就是$1.
以/etc/rc.d/rc 3为例来说明:通过$1也就是3来取得要执行的脚本目录,即/etc/rc$1.d/
(这里是/etc/rc3.d/)这个目录,这个目录下存放着许多的K*和S*文件。
在切换到指定的级别下时,K*文件先关闭,然后在启动S*文件,这些文件都是系统服务,且也是链接文件,真正的服务文件存在/etc/init.d/或者/etc/rc.d/init.d/这个目录下。
每个文件由两位数字##组成,这个数字表示的是服务启动或关闭的优先顺序,数字越小,越优先选定。
其中/etc/rc.local是一个脚本文件,是在系统最后才执行的一个文件
本文出自 “linux学习之路” 博客,谢绝转载!
原文地址:http://xslwahaha.blog.51cto.com/4738972/1530600