我正在阅读 wait
和 waitpid
函数并看到以下文本:
When a process terminates, either normally or abnormally, the kernel notifies the parent by sending a
SIGCHLD
signal to the parent.Then the parent should handle the termination.
我对为什么 parent 必须知道它的 child 被终止感到困惑。当然,如果 child 已经终止,它就消失了,永远不会消耗任何资源。
为什么 parent 必须知道它?
最佳答案
如果一个进程正在启动其他进程,它通常想要跟踪它们的状态。
当一个子进程终止时,它几乎完全消失了。它变成了一个僵尸进程,并为另一个进程(通常是父进程)保留了足够的信息,以便能够告诉为什么它终止(基本上,它的返回代码)。
然后,当父级成功地对子级执行wait
时,将返回返回码并清除子级的最后残余。
而且 parent 没有这样做。有多种方法可以启动将修改其父进程的子进程,您可以看到它们之间的区别:
sleep 3601 &
( sleep 3602 & )
后者启动一个子 shell,并从其中开始 sleep ,然后子 shell 退出,这样子就得到一个新父级:
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
你可以在这里看到 sleep
进程中的 一个 仍然有我的 shell 作为父进程,但另一个已经被推上进程树到 upstart
。
通常,它被 init
(a) 采用,它有专门用于收割僵尸的代码(wait
-ing on them then throw去掉返回码)。
(a) 现代 UNIX 可以通过使用 PR_SET_CHILD_SUBREAPER
参数调用 prctl()
来覆盖它。这将进程标记为子收割者。
然后,当父进程死亡时,沿着进程树向上移动的第一个子收割者将成为其直接子进程的新父进程(init
是最终收割者)。
您实际上可以在上面的流程树中看到这一点,很明显 upstart
已经完成了这一点。这意味着 它 是第一个在树上行走时发现的子收割者,所以属于死亡进程的 sleep
并没有一直走到 初始化
。
关于c - 父进程跟踪子进程的终止状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53313786/