c - 父进程跟踪子进程的终止状态

标签 c unix process

我正在阅读 waitwaitpid 函数并看到以下文本:

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/

相关文章:

c++ - 同时从 2 个线程读取全局变量

c - 双击运行可执行文件

c - 如何确定进程的状态(即它是否是僵尸进程)

Golang - 按名称杀死进程

c - 仅使用指针在动态结构中使用二维数组的 fscanf

c - 使用 if 语句中定义的变量

linux - MongoDB - Ubuntu crouton - 无法启动服务

linux - 监视文件上的 grep 无法正常工作

linux - 使用保存在文本中的名称创建多个文件

c - 按顺序 fork 进程有 4 个子进程?