我正在阅读wait
和waitpid
函数,并遇到以下文本:
当进程正常或异常终止时,内核会通过向父进程发送
SIGCHLD
信号来通知父进程。然后,父母应处理终止。
我对父母为什么必须知道其孩子被终止的原因感到困惑。当然,如果孩子已经终止,那么它就消失了,永远不会消耗任何资源。
出于什么原因父母必须了解它?
答案 0 :(得分:3)
如果一个进程正在启动其他进程,则通常要跟踪其状态。
子进程终止时,几乎会完全消失。它变成了僵尸进程,只保留了足够的信息以供另一个进程(通常是父进程)使用,以告知为什么终止(基本上是其返回码)。
然后,当父级成功对子级执行wait
时,将返回返回码,并清除子级的最后残余物。
而父母没有没有这样做。有几种方法可以启动将修改其父级的子进程,您可以看到以下两者之间的区别:
sleep 3601 &
( sleep 3602 & )
后者启动一个子外壳,然后从其中启动睡眠,然后该子外壳退出,以便该子获得一个 new 父级:
1 /sbin/init splash
|
+-- 1121 /usr/sbin/lightdm
|
+-- 1846 /usr/sbin/lightdm --session-child 12 19
|
+-- 2078 /sbin/upstart --user
|
+--- 29899 sleep 3602
|
+--- 2929 /usr/lib/gnome-terminal/gnome-terminal-server
|
+--- 2935 bash (my bash shell)
|
+--- 29891 sleep 3601
您可以在此处看到{em {em}}中的一个{em} 仍以我的shell作为父级,但是另一个已被推入进程树到sleep
。 / p>
通常,它被upstart
(a)所采用,该代码具有专门用于收割僵尸的代码(init
-插入僵尸,然后扔掉返回代码)。
(a)现代UNIX可以通过使用wait
参数调用prctl()
来覆盖它。这会将进程标记为次要收割者。
然后,当父母死亡时,步行到流程树的第一个子收割者成为其直系子代的新父母(PR_SET_CHILD_SUBREAPER
是最终收割者)。
您实际上可以在上面的过程树中看到这一点,很明显init
已经做到了这一点。这意味着 it 是在树上行走时发现的第一个子收割者,因此属于死亡进程的upstart
并没有一直上升到sleep