现在的位置:首页  /  云计算培训   /   云计算技术教程

sysVinit的正常启动顺序详细解析教程

来源: 薪享宏福
发布时间: 2019年03月21日
分享到:
既然systemd由sysVinit进化而来,因此为了更好地掌握systemd的原理和启动过程,首先我们详细分析-下sysVinit的启动方式。 下面我们以典型的CentOS5系统为例,为大家绍sysVinit体系下的启动顺序。
 
1、在Linux系统的启动过程中,首先由BIOS加电自检,之后将引导功能交给GRUB进行引导,用户可以根据界面提示来自由地选择不同版本的内核。
2、内核在引导完成之后,会加载第一个进程init ,这时就正式进入了sysVinit的引导环境, init进程在磁盘的"/sbin/init" 这个位置。之后所有的进程都是由它派生( fork )出来的,它的PID永远为1。
 
3、init程序运行时会加载配置文件/etc/inittab ,在配置文件中根据指定的参数来确定自己的启动级别( runlevel) ,不同的启动级别可用来定义一组不同服务的启动顺序,在默认情况下会有0~6共7个启动级别,也就是说用户可以定义7种(实际上是5种)不同的启动方式,以保证用户可以灵活地进行服务启动顺序的设置。默认情况下,在生产环境中我们将启动级别设置为3 
 
4、init程序会按照默认的级别来逐个加载一组服务,首先会加载各个外设的硬件驱动,然后加载基础服务,如网络参数、蓝牙、软件raid、LVM逻辑等服务,之后再加载其他的应用服务。全部加载完成之后会进入等待用户登录的界面,来完成一次启动过程。这就是sysVinit的启动过程,弓导过程大量使用了Shell脚本,以方便运维工程师分析启动过程中都执行了哪些操作,这种简单又直接的启动方式很适合运维工程师去理解启动的过程,但启动效率却很低。
 
sysVinit的启动过程如下图所示:
为了便于对比不同的启动程序之间的差异,下面将更具体地分析下/etc/inittab文件中的内容。
 
1、init进程加载/etc/inittab配置文件的部分,获得运行级别后并不会根据级别立即启动这组服务程序, init进程会为系统执行初始化动作。这个初始化动作是由/etc/inittab的下列选项来完成的:
 
sic:sysinit:/etc/rc.d/rc.sysinit
 
它的含义是在系统启动各个服务程序之前执行/etc/rc.d/rc.sysinit脚本,这个脚本是串行地将主机名、文件系统、swap、 SELinux、udev、内核参数、系统时钟、RAID、 LVM等服务启动时可能会依赖的功能先运行起来,然后再加载指定级别的服务。如果我们测量一次完整的启动时间,会发现rc.sysinit脚本的运行时间占用了大部分的启动时间,因为它为后面的各级别服务准备了基础环境,而不关心后面的服务是否会用到这些资源,从而造成了大量的启动时间的浪费。
 
2、加载服务又是怎样实现的呢?可以通过设置/etcinittab配置文件的"id: 3: initdefault :”这一行语句来更改系统默认的运行级别。在配置文件中还有这样的内容:
l0:0:wait:/etc/rc.d/rc 0
I1:1:wait:/etc/rc.d/rc 1
I2:2:wait:/etc/rc.d/rc 2
I3:3:wait:/etc/rc.d/rc 3
I4:4:wait:/etc/rc.d/rc 4
I5:5:wait:/etc/rc.d/rc 5
I6:6:wait:/etc/rc.d/rc 6
 
这里是一个分支,用于保证系统会加载到一组指定的服务,而不是加载全部的服务。而前面的wait标志,会让系统逐个加载服务直到加载完所有的服务后才继续下一步的启动。
 
根据initdefault给定的级别(这里是级别3),执行相应的服务。系统会执行/etc/rc.d/rc 3的Shell脚本,下面将跟踪/etc/rc.d/rc这个脚本,
主要逻辑如下:
 
runlevel="$1" #获取命令的参数
 
for i in /etc/rc$runlevel.d/K* ; do
 
#进入/etc/rc3.d/目录,依次执行以K00~K99开头的程序并增加stop
参数
$i stop
 
done
 
for i in /etc/rc$runlevel.d/S* ; do
 
#进入/etc/rc3.d/目录,依次执行以S00~S99开头的程序并增加start参数
 
$i start
 
done
 
打开/etc/rc1.d到/etc/rc5.d目录会发现大部分服务是以S开头的符号链接,而rc0.d和rc6.d下则是大量的以K开头的符号链接。运维工程师通过chkconfig命令就可以改变这些符号链接开头的S或K标记。而S或K标记后面的两位数字就是用来确定启动顺序的。
 
从这个逻辑我们不难发现,服务启动的过程是顺序完成的,而且在前一个服务没有执行完成之前,后面的程序都要等待;利用这种方式启动服务的好处还是简单,但这一过程会让现代计算机 (多核并发)的机制产生严重的资源浪费,因为仅有单线程在工作。鉴于上面的这种顺序弓导的情况, CentOS 6采用了Upstart I具来代替sysVinit进行引导, Upstart对rc.sysinit脚本做了大量的优化,它将启动需要做的每一个服务都封装成一个任务( job) ,并且为每一个任务增加一个状态,在启动时制定一些状态,并根据状态来确认每个任务运行到哪一步了,然后使用事件( event )机制和其他任务进行通信,这样就缩短了系统初始化时的启动时间。有了Upstart之后,我们在同样的硬件环境下进行了启动时间的比较,发现启动一套标准的CentOS 6系统要比CentOS5系统快很多。但是我们还发现如果在服务引导的部分还有可以优化的余地,即rc3.d部分引导服务的时候仍然是串行的,那么我们还可以对这部分缩短启动时间,接下来我们看看systemd是怎么做的。

相关推荐:

sysVinit方式下系统的启动特点

systemd方式 下系统的启动特点

运维培训班的学员要明白开发同样重要

PHP运维常见问题以及解决办法