<img src="https://i-blog.csdnimg.cn/blog_migrate/6a4db3f222ef87dfd5335c34493db2ab.png" data-rawwidth="870" data-rawheight="602" class="origin_image zh-lightbox-thumb" width="870" data-original="https://pic1.zhimg.com/3b9eab005d0e535e8adcfab11dd6f7e8_r.jpg">

如流程图所示,RHEL的启动过程按步骤大致可以分为:
POST加电自检-->BIOS(Boot Sequence)-->加载对应引导上的MBR(bootloader) -->主引导设置加载其BootLoader-->Kernel初始化-->initrd—>/etc/init进程加载/etc/inittab
从加载BootLoader(RHEL下为Grub)开始,会发生以下事情.
1. 藉由Grub的管理,读取Kernel内核文件(/boot/vmlinuz),解压至主内存,利用内核的功能,进行第二次硬件检测(第一次发生在POST开机自检时)
2. 加载Initial RAM Disk(/boot/initrd),使之在内存中解压缩为根目录,kernel藉此完成驱动程序的加载,,最终释放虚拟文件系统,并挂载实际的根目录文件系统.
3. 在核心加载完毕,进行完硬件侦测与驱动程序加载后,内核会启动第一个进程/sbin/init, init进程将会读取/etc/inittab,在/etc/inittab中,大致规定了以下动作:
- 取得 runlevel 亦即默认运行等级的相关等级.
- 使用 /etc/rc.d/rc.sysinit 进行系统初始化
- 根据runlevel调用相关启动脚本,以启动相应的系统服务
- 其他一些系统设置,最终完成系统启动.
/sbin/init 最主要的功能就是准备软件运行的环境,包括系统的主机名称、网络配置、语系处理、文件系统格式及其他服务的启动等,而所有的动作都根据在/etc/inittab中的配置.
/etc/rc.d, 里面存放了rc.local, rc.sysinit, init.d, rcX.d (X包括0-6对应相对runlevel)
/etc/rc.d/init.d, 存放了各种系统服务的启动关闭的管理脚本,/etc/init.d是他的一个目录链接.
/etc/rc.d/rcX.d, 里面存放了一些脚本,脚本名字以K开头的,表示STOP动作,名字以S开头,表示Start动作,名称中的数字表示执行次序,数字越小表示越先执行.
/etc/rcX.d是他的目录链接,但事实上rcX.d下文件本身就是指向/etc/rc.d/init.d下脚本的链接文件.
/etc/rc.d/rc.local, 有一个链接文件,路径在/etc/rc.local,
系统根据runlevel启动完rcX.d中的脚本之后,会调用rc.local脚本,如果你有一个脚本命令不论在3和5都想开机启动,那么就添加与此,免去rc3.d和rc5.d分别增加启动脚本工作量.
- 根据/etc/inittab启动init进程
- init进程执行/etc/rc.d/rc.sysinit
- init进程完成run-level之间的各个服务启动(在/etc/rc.d/rcN.d下有一堆软连接l指向/etc/rc.d/init.d)
- init进程执行/etc/rc.d/rc.local(在/etc/rc.d/rcN.d下有一个软连接S99local指向/etc/rc.d/rc.local)
- init进程完成tty
这里init过程涉及到若干初始化的配置文件、脚本、目录,这些初始化相关的配置文件、脚本、目录看起来似乎并没有太多层次感(注意:仅仅是看起来似乎是没有层感)。
分析问题,应该先抓住主要矛盾——这些繁杂的文件有一个主线,那就是/etc/inittab这个文件。inittab详细规划、控制了启动的详细过程。掌握了inittab,才能对这些繁杂的文件目录树有一个基本的了解。至于inittab的详细语法、内容请自行man。简要的说(不够准确),linux的inittab过程可以归结为三大步骤:
- 系统初始化:rc.sysinit
- 服务启动:rc N 启动rcN.d下的服务
- 本地初始化:rc.local
考虑到这些配置文件、目录、程序有各种乱七八糟的link,建议先抛开繁复的文件链接不管,得到如下的主干层次结构(#字符后面注解了各类文件的作用):
/etc/inittab #初始化的主干文件
/etc/rc.d #初始化的相关rc文件目录,下面有五个文件夹
- /etc/rc.d/rc.sysinit #系统初始化程序
- /etc/rc.d/rc #相应启动级别下的关键初始化程序,用以执行相应/etc/rc.d/rcN.d下的所有程序
- /etc/rc.d/rcN.d/ #N取值范围为[0,6],含有各类S和K开头的软连接文件,软连接至rc.d/init.d/下各类服务和rc.local脚本
- /etc/rc.d/init.d/ #含有各类服务程序
- /etc/rc.d/rc.local #本地初始化程序
rc.local是如何发生作用的?我们说inittab规划了初始化的详细过程,但是inittab中为什么没有规划rc.local调用的相关设定?
这个问题的关键在于上文提到的相关目录层级中的相应rc级别下的关键初始化程序/etc/rc.d/rc,这个程序接收一个0-6范围内的整数,执行rcN.d下的服务脚本(inittab的第二大步骤),而在rcN.d下有一个软连接S99local指向了rc.local(inittab的第三大步骤)。因此严格来说,inittab的第三步骤实际发生在第二步骤内,这也是rc.local得以执行的关键。
至于Ubuntu,这个发行版的Linux并没有inittab这个表。原因是他们认为上文这种依次执行的串行方式费时,于是采用了upstart的基于event的方式。类似的,Ubuntu也有相应的配置文件,具体的相关名字、目录层级记得不太清楚了,由于手头暂时没有可用的Ubuntu机器,