首页 > 解决方案 > 父进程跟踪子进程的终止状态

问题描述

我正在阅读waitandwaitpid函数并遇到以下文本:

当进程正常或异常终止时,内核通过向父进程发送SIGCHLD信号来通知父进程。

然后父母应该处理终止。

我很困惑为什么父母必须知道它的孩子被终止了。当然,如果孩子已经终止,它就消失了,永远不会消耗任何资源。

为什么父母必须意识到这一点?

标签: cunixprocess

解决方案


如果一个进程正在启动其他进程,它通常希望跟踪它们的状态。

当子进程终止时,它几乎完全消失。它变成了一个僵尸进程,并且为另一个进程(通常是父进程)保留了足够的信息,以便能够说出它终止的原因(基本上是它的返回码)。

然后,当父级成功对子级执行 await时,返回返回码并清理子级的最后剩余部分。

父母不必这样做。有一些方法可以启动将修改其父进程的子进程,您可以看到两者之间的区别:

sleep 3601 &
( sleep 3602 & )

后者启动一个子 shell,并在其中启动睡眠,然后子 shell 退出,以便子 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

您可以在此处看到,其中一个进程仍将我的 shell 作为父进程,sleep但另一个进程已被推上进程树到upstart.

通常,它被init(a)采用,它具有专门用于收割僵尸的代码(wait-ing 在它们上然后丢弃返回代码)。


(a)现代 UNIX 可以通过调用参数来覆盖prctl()PR_SET_CHILD_SUBREAPER。这将一个进程标记为子收割机。

然后,当父节点死亡时,沿着进程树向上移动的第一个子节点成为其直接子节点的新父节点(init最终成为最终节点)。

您实际上可以在上面的流程树中看到这一点,很明显upstart已经做到了这一点。这意味着是在上树时发现的第一个子收割者,因此sleep属于死亡进程的那个没有一直上升到init.


推荐阅读