linux第一个用户进程init--sysvinit
在《linux系统启动》一文中介绍了计算机从按开机键到系统启动的流程,在流程启动的最后一步就是启动系统的第一个用户态进程init进程,其进程ID永为1(其实还有一个id为0的进程swap,即有名的idle进程,当cpu没有进程可以运行时就会自动运行此进程,严格意义上来讲此进程才是内核创建的第一个进程)。
本文介绍一下init进程启动之后以及操作系统运行过程中都做了什么操作,以及担当什么样的角色。
目前比较流行的init进程分为三种:sysvinit、upstart、systemd。本文先重点介绍一下sysvinit。很多linux发行版中使用了sysvinit(即sysvinit-XXX.rpm包),里面包含了/sbin/init、/sbin/telinit、/sbin/runlevel等进程。
init的执行分为三个阶段(参见linux-init-process-analyse.pdf)
虽然是三个阶段,但是设计者写代码时把三个阶段合一了,都包含在/sbin/init进程中,根据不同的条件来走不能的流程。详细信息可以参见linux-init-process-analyse.pdf,这里只介绍重点内容。
1,在系统启动阶段init进程读取/etc/inittab文件中配置并将所有配置组成一个链表,后面循环此链表,并对每一项进程操作。
对于/etc/inittab文件需要注意以下几点:
- 格式:id:runlevels:action:process
- id很重要,必须唯一,因为作者对init的实现是当有重复id时不是忽略掉,而是直接停止继续处理后面内容。
- action值为wait的配置项表示必须等我这个项操作完init才能去操作剩下的配置项,这导致了sysvinit机制很难并行执行,这一点也是upstart与systemd机制出现的原因。action值为respawn表示,这个配置项中的process(如图中的mingetty)退出了,init进程有责任把此进程再重新拉起来。所以大家在登录linux串口时即使杀掉tty进程也会回到登录界面,就是这个原因。
- 想在系统启动阶段做一些特殊操作的话就可以从这里面入手,例如init会执行/etc/rc.d/rc脚本,可以添加自己的脚本文件来实现想要的功能。
2,系统启动过程中init执行完/etc/inittab中需要执行的操作之后,系统就算真正的启动了,这个时候init进程就会进入第三个阶段,即作为一个deamon来运行。
- 首先创建一个管道/dev/initctl
- 其次通过select系统调用等待在/dev/initctl管道的一端,一旦有进程往另一端写入希望init process执行的request,init 3就会分析该request,然后执行要求的动作(见check_init_fifo函数)
- 同时当有signal发送给init process时,init在signal handler中并不马上处理该signal,而仅仅是在全局变量got_signals中置一下该signal发生过的标志,真正的处理是在init 3的循环中的process_signals()中。
3,当具有root权限的用户通过运行init来切换运行级别时,这种情况就称为init的第二个阶段,当然第三个阶段也就是为了处理这个阶段的请求才作为deamon来运行的。也即后面的交互都是第二阶段和第三阶段的交互,其桥梁就是管道/dev/initctl。
在管道/dev/initctl中传输的request格式如下:
struct init_request {
int magic; /* Magic number */
int cmd; /* What kind of request */
int runlevel; /* Runlevel to change to */
int sleeptime; /* Time between TERM and KILL */
union {
struct init_request_bsd bsd;
char data[368];
} i;
};
更多推荐
所有评论(0)