一、Init程序
Init程序是linux启动过程中,初始化所有设备驱动程序和数据结构后,由内核启动的第一个用户级程序,并由Init程序完成系统
启动过程。各发行版本中主要使用的Init程序有Sysvinit、Upstart、Systemd,本文将介绍这三种Init程序。
(一)、Sysvinit
1. 运行级别
Sysvinit是较早使用的Init程序,基于运行级别。系统以何种运行级别启动由Init读取/etc/inittab文件中的缺省级别设置来确定。
运行级别的定义具体如下:
0 => 关机(halt)
1 => 单用户模式(single)
2 => 多用户
3 => 完整的多用户模式(标准的运行级)
4 => 系统保留
5 => 完整的多用户,使用X11(X window)
6 => 重启(reboot)
Ubuntu很早就不使用Sysvinit了。现在的版本默认是没有/etc/inittab文件的,且运行级别的定义也有不同,具体如下:
0 => 关闭系统(halt)
1 => 单用户模式(single)
6 => 重启(reboot)
2,3,4,5 => 多用户模式(multi-user)
说明:这里的2、3、4、5都没有区分,是留给用户自己设置的。比如,修改ubuntu默认的运行级别为3,然后修改模式3的相关服务,可达到个人定制的目的。
2. 服务启动
启动与关闭服务的脚本存放在/etc/rc[?].d目录下。其中[?]表示0~6,分别对应级别0~6。/etc/rcS.d/路径下的脚本会先于/etc/rc[?].d/
执行。/etc/rc.local会在/etc/rc[?].d/路径下的脚本执行完成后,最后执行。例如:运行级别为2,将执行/etc/rc2.d/下的脚本。
脚本命名的方式:K开头(k=>kill)、S开头(S=>start)。K、S后面跟着的数字代表执行优先级,数字越小,执行顺序越高
(优先执行,比如K15优先于K20被执行)。当执行K开头的脚本,比如,K20acpid会执行/etc/init.d/acpid脚本,并给脚本传递一个
stop参数,指示其关闭acpi daemon服务。S开头的会传递start参数,指示其开启服务。而且/etc/rc[?].d/下面的脚本都是软链接,指向
/etc/init.d/中真正的执行脚本。若想要添加自定义的服务,需要将自定义服务的启动脚本放到/etc/init.d/路径下,并在对应的运行级别
目录下为其添加软链接。
命令:service 服务名 start | stop | restart 或者/etc/init.d/ 服务名 start | stop | restart
服务管理工具:chkconfig sysv-rc-conf
说明:
在Ubuntu中系统定义的服务存放在/etc/services文件中。在另一些发行版本中,部分非常驻服务由xinetd服务控制。xinetd服务配置文件保存在/etc/xinetd.conf。
例如Telnet服务就是由xinetd代理服务的。
3. Init执行流程--Sysvinit时代Linux启动流程:
1. BIOS
2. MBR
3. Grub
4. Linux-Kernel
5. Init
a. 运行/sbin/init
b. 读取/etc/inittab(该文件定义了运行级别)
c. 执行/etc/rc.d/rc-sysinit
d. 执行/etc/rcS.d/ 目录下的脚本
e. 切换到默认的运行级别执行。假设运行级别是5,则执行/etc/rc5.d/目录下的脚本
f. 执行/etc/rc.local(用户自定义的开机服务可放到该脚本中)
g. 执行/bin/login(此时已完成Init全过程)
6. 完成系统初始化,用户登录。
(二)、Upstart
Upstart init daemon是Sysvinit daemon的替代者,基于事件。可在系统启动、关闭、任务状态改变时启动或关闭服务。
1. 事件和作业
a. 事件:
Event就是Init得到的关于服务状态的变更信息。用户可通过initctl emit命令来手动触发一个事件,但通常情况下,事件是自动触发的。
Upstart有三种事件类型:
1) Signal Event:异步且非阻塞;
2) Method Event:同步且阻塞;
3) Hook Event:同步且阻塞。
Upstart的三个主要进程:
1) init:Upstart的主进程(PID=1)。职责是读取配置文件,处理各种服务和应用程序的依赖关系。根据事件来启动不同的功能和服务,
并动态的进行管理。
2) initctl:Upstart的事件管理器。可被应用程序用来通知Init哪些事件发生。initctl list可类比Sysvinit的chkconfig。
3) telinit:管理运行级别。要研究Upstart是如何兼容Sysvinit的,就要从telinit命令入手。
附:/etc/init/rc-sysinit.conf脚本中telinit的使用(省略部分,只留下关键的):
# rc-sysinit - System V initialisation compatibility
#
# This task runs the old System V-style system initialisation scripts,
# and enters the default runlevel when finished.
start on (filesystem and static-network-up) or failsafe-boot
stop on runlevel
env DEFAULT_RUNLEVEL=2
emits runlevel
task
script
# Check for default runlevel in /etc/inittab
if [ -r /etc/inittab]
then
eval "$(sed -nre 's/^[^#][^:]*:([0-6sS]):initdefault:.*/DEFAULT_RUNLEVEL="\1";/p' /etc/inittab || true)"
fi
# Run the system initialisation scripts
[ -n "${FROM_SINGLE_USER_MODE}" ] || /etc/init.d/rcS
# Switch into the default runlevel
telinit "${DEFAULT_RUNLEVEL}"
end script
b. 作业:
job是一个工作的单元,一个任务或一个服务。用户可以用initctl start和initctl stop命令手动启动或终止一项job。
分类:
1) 任务(Task job):运行、并在执行结束后返回到等待状态的job;
2) 服务(Service job):后台服务进程,通常不会自己结束的job;
3) 抽象作业(Abstract job):只存在于Upstart内部。没有PID,定义“永久运行”的job。
2. 服务启动
Upstart的服务启动配置放在/etc/init/目录下,以服务名.conf 文件存放。
在上图lightdm.conf配置文件中:
start on:服务的依赖关系;
emits:命令行发起事件。
在上图rsyslog.conf配置文件中:
exec:服务启动命令;
respawn:设置服务异常停止后服务自动重启;
script ... end script==>服务启动前后执行脚本。
说明:
需要开机启动自定义服务,只要向/etc/init/中添加自定义服务*.conf配置文件,并添加启动文件到/etc/init.d/即可。
命令/工具:initctl list==>查看所有服务状态 initctl start | stop | restart 服务名。还有一个命令update-rc.d也可以设置服务启停等,包含在insserv软件包中。
3. Init执行流程--Upstart时代Linux启动流程:
1. BIOS
2. MBR
3. Grub
4. Linux-Kernel
5. Inita. 运行/sbin/init
b. Upstart内部初始化,触发startup事件
c. 触发依赖startup事件的服务,主要包括挂载文件系统、本地回环网络(即定义了start on startup的服务脚本)
d. 触发rc-sysinit事件(/etc/init/rc-sysinit.conf),首先执行/ec/rcS.d/目录下的脚本(事实上,此后的过程与Sysvinit执行过程类似)
e. 切换到默认的运行级别执行脚本。例如:/etc/rc2.d/目录下的脚本(Ubuntu默认是"env DEFAULT_RUNLEVEL=2"
telinit "${DEFAULT_RUNLEVEL}")
f. 执行/etc/rc.local
g. 执行/bin/login(完成Init过程)
6. 完成系统初始化,用户登录。
说明:很多细节的东西还不清楚,有待研究。
(三)、Systemd
1. 基本概念及原理
Systemd与Sysvinit完全兼容,有更清晰的服务依赖关系,开机系统初始化服务并行启动,更少的shell开销。对应于运行级别的
概念,Systemd有target的概念与之对应,例如multi-user.target。
以下是FedoraProject官网对Systemd的介绍(Fedora目前已经使用Systemd作为默认的Init):
Systemd是Linux下一个与SysV和LSB初始化脚本兼容的系统和服务管理器。Systemd使用socket和D-Bus来开启服务,提供基
于守护进程的按需启动策略,保留了Linux cgroups的进程追踪功能,支持快照和系统状态恢复,维护挂载和自挂载点,实现了各服
务间基于从属关系的一个更为精细的逻辑控制,拥有前卫的并行性能。Systemd无需经过任何修改便可以替代Sysvinit 。
2. 服务启动
服务配置文件放在/lib/systemd/system/目录下,以*.service命名。没有运行级别的概念,完全兼容Sysvinit。
rsyslog.service文件格式:
[Unit]
Description=System Logging Service
[Service]
ExecStartPre=/bin/systemctl stop systemd-kmsg-syslogd.service
ExecStart=/usr/sbin/rsyslogd -n -c5
Sockets=syslog.socket
StandardOutput=null
[Install]
WantedBy=multi-user.target
命令:systemctl enable | disable *.service ==>设置服务 自动启动 | 非自动启动
systemctl start | stop | restart *.service ==>服务启动 | 停止 | 重启
systemctl status *.service ==>查看服务状态
工具:systemadm ==>图形化的管理工具
3. Init执行流程--Systemd时代Linux启动流程:
暂先留空,待以后再补充。
附:linux2.6.32.61版本的内核Init代码( /init/main.c ),说明kernel与/sbin/init的关系。
static noinline int init_post(void)
__releases(kernel_lock)
{
/* need to finish all async __init code before freeing the memory */
async_synchronize_full();
free_initmem();
unlock_kernel();
mark_rodata_ro();
system_state = SYSTEM_RUNNING;
numa_default_policy();
if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
printk(KERN_WARNING "Warning: unable to open an initial console.\n");
(void) sys_dup(0);
(void) sys_dup(0);
current->signal->flags |= SIGNAL_UNKILLABLE;
if (ramdisk_execute_command) {
run_init_process(ramdisk_execute_command);
printk(KERN_WARNING "Failed to execute %s\n",
ramdisk_execute_command);
}
/*
* We try each of these until one succeeds.
*
* The Bourne shell can be used instead of init if we are
* trying to recover a really broken machine.
*/
if (execute_command) {
run_init_process(execute_command);
printk(KERN_WARNING "Failed to execute %s. Attempting "
"defaults...\n", execute_command);
}
run_init_process("/sbin/init");
run_init_process("/etc/init");
run_init_process("/bin/init");
run_init_process("/bin/sh");
panic("No init found. Try passing init= option to kernel.");
}
二、系统服务管理
以下是Ubuntu 12.04.5LTS所有的系统服务:
gf@gf:~$ initctl list
avahi-daemon start/running, process 1069 // 零配置网络服务
passwd stop/waiting // 管理用户密码和组数据
rc stop/waiting // System V runlevel compatibility
rsyslog start/running, process 970 // 增强的多线程系统日志
udev start/running, process 448 // 用户空间dev文件系统
upstart-udev-bridge start/running, process 446 // Bridge udev events into upstart
upstart-socket-bridge start/running, process 1118 // Bridge socket events into upstart
ureadahead-other stop/waiting // Read required files in advance for other mountpoints
console-setup stop/waiting // 控制台字体和键盘布局设置程序
hwclock-save stop/waiting // 查询和设置硬件时钟
irqbalance start/running, process 1332 // SMP(Symmetric Multi-Processing) 平衡中断的进程
failsafe stop/waiting // 启动故障自动检测
hybrid-gfx stop/waiting // nvidia的hybird检测(vi /etc/init/hybrid-gfx.conf)
// dpkg -S hybrid-detect 可以知道属于nvidia-common包的
modemmanager start/running, process 1148 // 管理调制解调器的dbus服务
rfkill-store stop/waiting // 无线网络设备管理
atd start/running, process 1341 // 计划任务
dbus start/running, process 1041 // 系统消息总线
failsafe-x stop/waiting // X启动故障自动检测
plymouth stop/waiting // 开机启动画面plymouth管理器
resolvconf start/running // 自动配置DNS信息
udev-fallback-graphics stop/waiting // take actions to initiate fallback graphics
control-alt-delete stop/waiting // control-alt-delete组合键
hwclock stop/waiting // 查询和设置硬件时钟
network-manager start/running, process 1165 // 系统网络连接管理
alsa-store stop/waiting // alsa音频系统服务
module-init-tools stop/waiting // 管理内核模块的工具
setvtrgb stop/waiting // 设置虚拟终端的颜色
shutdown stop/waiting // 关机
alsa-restore stop/waiting // alsa音频系统服务
cron start/running, process 1340 // 进程调度/计划任务
lightdm start/running, process 1324 // 桌面管理工具
mountall stop/waiting // 挂载服务
binfmt-support stop/waiting // 核心支持其他二进制文件格式
console stop/waiting // 终端
acpid start/running, process 1352 // acpi守护进程
rcS stop/waiting // System V single-user mode compatibility
ufw start/running // 防火墙
wait-for-state stop/waiting // ??
flush-early-job-log stop/waiting // Ensure cached output from jobs that finish before the disk is writeable are flushed
// to disk as soon as it does becomes writeable
friendly-recovery stop/waiting // 崩溃恢复
rc-sysinit stop/waiting // System V initialisation compatibility
anacron stop/waiting // 计划任务
udevtrigger stop/waiting // ??
container-detect stop/waiting // Track if upstart is running in a container
udev-finish stop/waiting // save udev log and update rules
hostname stop/waiting // set system hostname
networking stop/waiting // configure virtual network devices
tty1 start/running, process 1577 // 虚拟终端tty1
udevmonitor stop/waiting // log initial device creation
procps stop/waiting // sets kernel sysctl variables from /etc/sysctl.conf
rfkill-restore stop/waiting // restore software rfkill state
ureadahead stop/waiting // read required files in advance
gf@gf:~$
后记:
以下是介绍Init的系列文章,图文并茂,值得参考。
浅析 Linux 初始化 init 系统,第 1 部分: sysvinit: http://www.ibm.com/developerworks/cn/linux/1407_liuming_init1/index.html
浅析 Linux 初始化 init 系统,第 2 部分: UpStart: http://www.ibm.com/developerworks/cn/linux/1407_liuming_init2/index.html
浅析 Linux 初始化 init 系统,第 3 部分: Systemd:http://www.ibm.com/developerworks/cn/linux/1407_liuming_init3/index.html
修订:
参考:
注:
推荐文章,写的很不错的(2015年4月12日)
《探索Linux系统的启动过程》:http://www.linuxidc.com/Linux/2015-04/116076.htm