在 Linux 中,您如何在新获取的 child 进程退出之前了解它们?
In Linux, how do you learn about newly acquired child processes before they exit?
我正在编写一个调用 prctl(PR_SET_CHILD_SUBREAPER, 1)
的程序。因此,它可能会获取对其 parent 何时退出一无所知的进程。我希望这个进程在所有 children 退出时退出,包括它成为 parent 的进程,否则它们将成为孤儿。
如何从 C 或 C++ 程序以合理的方式执行此操作?我不想一直打开 /proc
中的所有内容,也不想调用为我执行此操作的流程。无论如何,这是一个轮询解决方案,我更喜欢不涉及轮询的解决方案。
此外,跟踪所有 children 以找出他们何时调用 fork
也不是真正的选择。以防万一有人有那个好主意。
您不需要对 /proc
做任何花哨的事情。只需使用 wait()
。来自手册页:
PR_SET_CHILD_SUBREAPER (since Linux 3.4)
If arg2 is nonzero, set the "child subreaper" attribute of the calling process; if arg2 is zero, unset the attribute. When a
process is
marked as a child subreaper, all of the children that it creates, and their descendants, will be marked as having a
subreaper. In
effect, a subreaper fulfills the role of init(1) for its descendant processes. Upon termination of a process that is
orphaned (i.e.,
its immediate parent has already terminated) and marked as having a subreaper, the nearest still living ancestor subreaper will
receive
a SIGCHLD signal and be able to wait(2) on the process to discover its termination status.
所以你的进程只需要坐在一个循环中调用 wait
直到它 returns -1 并且 errno
被设置为 ECHILD
。这将在进程树中的 all 个进程退出时发生。只要你这样做,你就不需要知道什么时候获取新的子进程等待。
假设您有以下进程树,进程 1000 是收割者:
1000
|---1001
| |---1002
| |---1003
|
|---1004
|---1005
|---1006
第一次调用wait
时,1001和1004都需要先退出returns -1。现在假设 1004 退出:
1000
|---1001
| |---1002
| |---1003
|
|---1004 (dead)
|-----|---1005
|-----|---1006
死神中,wait
returns 1004,现在1001、1005、1006需要退出。接下来,1002退出:
1000
|---1001
| |---1002 (zombie)
| |---1003
|
|---1004 (dead)
|-----|---1005
|-----|---1006
收割者还没有从wait
return,因为1001仍然运行并且仍然可以wait
给1002。在这一点上,1002是僵尸.接下来,1001 调用 wait
:
1000
|---1001
| |---1002 (dead)
| |---1003
|
|---1004 (dead)
|-----|---1005
|-----|---1006
收割者的预期没有变化,因为 1001 等待 1002。然后 1005 退出:
1000
|---1001
| |---1002 (dead)
| |---1003
|
|---1004 (dead)
|-----|---1005 (dead)
|-----|---1006
wait
在死神 return 的 1005 中,现在需要 1001 和 1006 才能退出。然后1003退出:
1000
|---1001
| |---1002 (dead)
| |---1003 (zombie)
|
|---1004 (dead)
|-----|---1005 (dead)
|-----|---1006
同样,收割者的期望没有改变。现在1001退出:
1000
|---1001 (dead)
| |---1002 (dead)
|-----|---1003 (dead)
|
|---1004 (dead)
|-----|---1005 (dead)
|-----|---1006
现在 wait
在收割者 return 中连续两次,一次 returning 1001 一次 returning 1003。现在收割者只等待1006.一旦退出:
1000
|---1001 (dead)
| |---1002 (dead)
|-----|---1003 (dead)
|
|---1004 (dead)
|-----|---1005 (dead)
|-----|---1006 (dead)
wait
在死神returns 1006,下一次调用returns -1结束循环。
我正在编写一个调用 prctl(PR_SET_CHILD_SUBREAPER, 1)
的程序。因此,它可能会获取对其 parent 何时退出一无所知的进程。我希望这个进程在所有 children 退出时退出,包括它成为 parent 的进程,否则它们将成为孤儿。
如何从 C 或 C++ 程序以合理的方式执行此操作?我不想一直打开 /proc
中的所有内容,也不想调用为我执行此操作的流程。无论如何,这是一个轮询解决方案,我更喜欢不涉及轮询的解决方案。
此外,跟踪所有 children 以找出他们何时调用 fork
也不是真正的选择。以防万一有人有那个好主意。
您不需要对 /proc
做任何花哨的事情。只需使用 wait()
。来自手册页:
PR_SET_CHILD_SUBREAPER (since Linux 3.4)
If arg2 is nonzero, set the "child subreaper" attribute of the calling process; if arg2 is zero, unset the attribute. When a process is marked as a child subreaper, all of the children that it creates, and their descendants, will be marked as having a subreaper. In effect, a subreaper fulfills the role of init(1) for its descendant processes. Upon termination of a process that is orphaned (i.e., its immediate parent has already terminated) and marked as having a subreaper, the nearest still living ancestor subreaper will receive a SIGCHLD signal and be able to wait(2) on the process to discover its termination status.
所以你的进程只需要坐在一个循环中调用 wait
直到它 returns -1 并且 errno
被设置为 ECHILD
。这将在进程树中的 all 个进程退出时发生。只要你这样做,你就不需要知道什么时候获取新的子进程等待。
假设您有以下进程树,进程 1000 是收割者:
1000
|---1001
| |---1002
| |---1003
|
|---1004
|---1005
|---1006
第一次调用wait
时,1001和1004都需要先退出returns -1。现在假设 1004 退出:
1000
|---1001
| |---1002
| |---1003
|
|---1004 (dead)
|-----|---1005
|-----|---1006
死神中,wait
returns 1004,现在1001、1005、1006需要退出。接下来,1002退出:
1000
|---1001
| |---1002 (zombie)
| |---1003
|
|---1004 (dead)
|-----|---1005
|-----|---1006
收割者还没有从wait
return,因为1001仍然运行并且仍然可以wait
给1002。在这一点上,1002是僵尸.接下来,1001 调用 wait
:
1000
|---1001
| |---1002 (dead)
| |---1003
|
|---1004 (dead)
|-----|---1005
|-----|---1006
收割者的预期没有变化,因为 1001 等待 1002。然后 1005 退出:
1000
|---1001
| |---1002 (dead)
| |---1003
|
|---1004 (dead)
|-----|---1005 (dead)
|-----|---1006
wait
在死神 return 的 1005 中,现在需要 1001 和 1006 才能退出。然后1003退出:
1000
|---1001
| |---1002 (dead)
| |---1003 (zombie)
|
|---1004 (dead)
|-----|---1005 (dead)
|-----|---1006
同样,收割者的期望没有改变。现在1001退出:
1000
|---1001 (dead)
| |---1002 (dead)
|-----|---1003 (dead)
|
|---1004 (dead)
|-----|---1005 (dead)
|-----|---1006
现在 wait
在收割者 return 中连续两次,一次 returning 1001 一次 returning 1003。现在收割者只等待1006.一旦退出:
1000
|---1001 (dead)
| |---1002 (dead)
|-----|---1003 (dead)
|
|---1004 (dead)
|-----|---1005 (dead)
|-----|---1006 (dead)
wait
在死神returns 1006,下一次调用returns -1结束循环。