我正在编写一个调用prctl(PR_SET_CHILD_SUBREAPER, 1)
的程序。因此,它可能会获得对父母退出时一无所知的流程。我希望这个过程在所有孩子都退出时退出,包括那些成为父母的孩子,因为他们本来就是孤儿。
如何以合理的方式从C或C ++程序中执行此操作?我不想一直打开/proc
中的所有内容,或者打电话给我这样做的过程。无论如何,这是一个民意调查解决方案,我更倾向于一个不涉及民意调查的解决方案。
此外,让所有孩子知道他们何时打电话fork
也不是一个选择。以防有人有这个好主意。
答案 0 :(得分:2)
你不需要对/proc
做任何奇特的事情。只需使用wait()
即可。从手册页:
PR_SET_CHILD_SUBREAPER(自Linux 3.4开始)
如果arg2非零,请设置" child subreaper"调用过程的属性;如果arg2为零,则取消设置该属性。当一个 过程是 标记为子子区域,它创建的所有子项及其后代将被标记为具有 subreaper。在 效果,subreaper为其后代进程履行init(1)的角色。 终止进程时 孤儿(即 它的直接父母已经终止了并且标记为有一个subreaper,最近的仍然生活的祖先subreaper将 接收 SIGCHLD信号,能够等待(2)流程发现其终止状态。
因此,您的流程只需要在循环中调用wait
,直到它返回-1并将errno
设置为ECHILD
。当进程树中的所有进程退出时,就会发生这种情况。只要你这样做,你就不需要知道何时获得新的子进程等待。
假设您有以下流程树,其中流程1000是收割者:
1000
|---1001
| |---1002
| |---1003
|
|---1004
|---1005
|---1006
当您第一次调用wait
时,1001和1004都需要在返回-1之前退出。现在假设1004退出:
1000
|---1001
| |---1002
| |---1003
|
|---1004 (dead)
|-----|---1005
|-----|---1006
在收割者中,wait
返回1004.现在1001,1005和1006需要退出。接下来,1002退出:
1000
|---1001
| |---1002 (zombie)
| |---1003
|
|---1004 (dead)
|-----|---1005
|-----|---1006
收割者还没有从wait
返回,因为1001仍然在运行,并且仍然可以wait
为1002.此时,1002是一个僵尸。接下来,1001调用wait
:
1000
|---1001
| |---1002 (dead)
| |---1003
|
|---1004 (dead)
|-----|---1005
|-----|---1006
自从1002等待1001后,收割机的预期没有变化。然后1005退出:
1000
|---1001
| |---1002 (dead)
| |---1003
|
|---1004 (dead)
|-----|---1005 (dead)
|-----|---1006
收割机中的 wait
返回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
连续两次返回,一次返回1001并返回1003.现在收割机只等待1006.一旦退出:
1000
|---1001 (dead)
| |---1002 (dead)
|-----|---1003 (dead)
|
|---1004 (dead)
|-----|---1005 (dead)
|-----|---1006 (dead)
收割者中的 wait
返回1006,下一个调用返回-1结束循环。