上一篇文章讲到了系统从开机到内核加载的过程,本文继续接着讲用户运行模式启动的过程。
当内核加载之后必须要运行用户程序才能是系统变为可用,现在一般有三种init系统:
- sysvinit
- upstart
- systemd
1.传统的sysvinit方式
缺点:启动较慢,适用于服务器和PC,不适合于移动端。
sysvinit首先会去读取系统的配置文件/etc/inittab。/etc/inittab的语法是利用冒号(:)将每条设置语句分割成四个字段,每个字段的含义如下:
[设定项目]:[run level]:[init的动作行为]:[执行命令或者脚本]
1.设定项目:最多四个字符,代表init的主要工作项目,只是一个简单的说明;
2.run level:该项目在哪些run level地下执行的意思,如果是123则代表在run level 1,2,3都会执行,注意有些行为和 run level无关,如sysinit、boot、bootwait;
3.init的动作行为:
init动作行为 | 说明 |
initdefault | 指定系统启动之后进入的run level,如果没有指定那么需要在控制台手动输入 |
sysinit | 系统启动的时候执行的进程。它会在任何boot和bootwait项之前执行,忽略run level字段。 |
wait | 在进入指定的run level之后立即执行,init脚本会在它结束之后执行。 |
ctrlaltdel | 当收到SIGINT信号时执行的动作。 |
respawn | 该脚本在终止之后会立即重启。 |
sysinit、boot、bootwait等action将在系统启动时无条件运行,而忽略其中的runlevel。其余的action(不含initdefault)都与某个runlevel相关。更多的信息请参考man inittab。
4.执行指令或者脚本:表示在相应的条件满足的时候需要执行的指令或者脚本。
下面是inittab文件
#
# inittab This file describes how the INIT process should set up
# the system in a certain run-level.
# Default runlevel. The runlevels used by RHS are:
# 0 - halt (Do NOT set initdefault to this)
# 1 - Single user mode
# 2 - Multiuser, without NFS (The same as 3, if you do not have networking)
# 3 - Full multiuser mode
# 4 - unused
# 5 - X11
# 6 - reboot (Do NOT set initdefault to this)
#
id:3:initdefault:
sysvinit使用运行级别来定义“预定的运行模式”从而实现不同情况下实现不同的初始化,不同模式下需要初始化启用的进程和需要初始化的准备是不一样的,用户只需要指定需要进入哪种模式,sysvinit 将负责执行所有该模式所必须的初始化工作。上面的语句设定系统的启动级别是3.
# System initialization.
si::sysinit:/etc/rc.d/rc.sysinit
sysinit语句用来设定系统在任何boot和bootwait项之前执行的操作,因为该操作忽略运行级别,所以运行级别该项为空。系统初始化的脚本是/etc/rc.d/rc.sysinit。该脚本主要是进行系统的初始化,包括网络环境的初始化,磁盘挂载,系统模块的加载等。
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
上面的语句用来设定不同模式下的初始化脚本目录,例如本系统3对应/etc/rc.d/rc3.d下的脚本。/etc/rc.d/rcX.d/目录中的这些启动脚本实际上都是一些链接文件,而不是真正的rc启动脚本,真正的rc启动脚本实际上都是放在/etc/rc.d/init.d/目录下。而这些rc启动脚本有着类似的用法,它们一般能接受start、stop、restart、status等参数。
/etc/rc.d/rcX.d/中的rc启动脚本通常是K或S开头的链接文件,对于以S开头的启动脚本将以start参数来运行(S后面的数字是脚本执行的顺序)。而如果发现存在相应的脚本也存在K打头的链接,而且已经处于运行态了(以/var/lock/subsys/下的文件作为标志),则将首先以stop为参数停止这些已经启动了的守护进程,然后再重新运行。这样做是为了保证是当init改变运行级别时,所有相关的守护进程都将重启。
至于在每个运行级中将运行哪些守护进程,用户可以通过chkconfig或setup中的"System Services"来自行设定。常见的守护进程有:
amd:自动安装NFS守护进程
apmd:高级电源管理守护进程
arpwatch:记录日志并构建一个在LAN接口上看到的以太网地址和IP地址对数据库
autofs:自动安装管理进程automount,与NFS相关,依赖于NIS
crond:Linux下的计划任务的守护进程
named:DNS服务器
netfs:安装NFS、Samba和NetWare网络文件系统
network:激活已配置网络接口的脚本程序
nfs:打开NFS服务
portmap:RPC portmap管理器,它管理基于RPC服务的连接
sendmail:邮件服务器sendmail
smb:Samba文件共享/打印服务
syslog:一个让系统引导时起动syslog和klogd系统日志守候进程的脚本
xfs:X Window字型服务器,为本地和远程X服务器提供字型集
Xinetd:支持多种网络服务的核心守护进程,可以管理wuftp、sshd、telnet等服务
这些守护进程也启动完成了,rc程序也就执行完了,然后又将返回init继续下一步。
以下是/etc/rc.d/rc脚本,是通过此脚本传入运行级别参数间接调用/etc/rc.d/rc$RUNLEVEL.d下面的脚本文件的。
argv1="$1"//将参数1,即脚本运行级别存入argv1变量
# Get first argument. Set new runlevel to this argument.
[ -n "$argv1" ] && runlevel="$argv1" //给runlevel赋值
//判断是否有对应的目录存在
# Is there an rc directory for this new runlevel?
[ -d /etc/rc$runlevel.d ] || exit 0
//执行/etc/rc$runlevel.d目录下的执行脚本
# Now run the START scripts.
for i in /etc/rc$runlevel.d/S* ; do
check_runlevel "$i" || continue //执行结果为1
if [ "$subsys" = "halt" -o "$subsys" = "reboot" ]; then
export LC_ALL=C
exec $i start //执行脚本文件,传递start参数
fi
# Trap CTRL-ALT-DELETE
ca::ctrlaltdel:/sbin/shutdown -t3 -r now
# When our UPS tells us power has failed, assume we have a few minutes
# of power left. Schedule a shutdown for 2 minutes from now.
# This does, of course, assume you have powerd installed and your
# UPS connected and working correctly.
pf::powerfail:/sbin/shutdown -f -h +2 "Power Failure; System Shutting Down"
# If power was restored before the shutdown kicked in, cancel it.
pr:12345:powerokwait:/sbin/shutdown -c "Power Restored; Shutdown Cancelled"
//执行/sbin/mingetty脚本,启动终端,等待用户登录
# Run gettys in standard runlevels
1:2345:respawn:/sbin/mingetty tty1
2:2345:respawn:/sbin/mingetty tty2
3:2345:respawn:/sbin/mingetty tty3
4:2345:respawn:/sbin/mingetty tty4
5:2345:respawn:/sbin/mingetty tty5
6:2345:respawn:/sbin/mingetty tty6
# Run xdm in runlevel 5
x:5:respawn:/etc/X11/prefdm -nodaemon //启动Xwindow
当init.d/目录下的脚本执行完之后,Sysvinit 运行/etc/rc.d/rc.local 脚本。rc.local 是 Linux 留给用户进行个性化设置的地方,你可以把自己私人想设置和启动的东西放到这里,一台 Linux Server 的用户一般不止一个,所以才有这样的考虑。下面是rc.local的内容:
执行完对应的脚本之后,初始化过程结束。
参考资料
http://www.360doc.com/content/05/0823/14/126_8089.shtml
http://linux.vbird.org/linux_basic/0510osloader.php#process_2
https://www.ibm.com/developerworks/cn/linux/1407_liuming_init1/