alk*_*alk 24 c unix children parent process-reaper
流程A fork()流程B.
过程A死亡,因此init采用B.
监督者创建进程C.
C在某种程度上可以采用B init吗?
更新:
或者甚至可以让C直接采用B(当A死亡时),如果C是在A死之前创建的,而不是init成为B的中间父级?
更新1:
我也很感激任何关于为什么有可能以我所描述的方式采用一个过程可能是一件坏事或难以实现的评论.
Update-2 - 用例(父级和子级引用进程):
我有一个应用程序使用父级来管理一大堆子,这依赖于父级的管理工具.为了完成其工作,父母依靠通过孩子的终止通知,这通过接收相关SIGCHLD信号来完成.
如果父母本身因某些意外(包括segfaulting)而死亡,我需要重新启动整个"家庭",因为现在不可能在孩子终止时触发某些事情(这也可能是由于段错误).
在这种情况下,我需要关闭所有孩子并完成一个完整系统的重启.
避免这种情况的一种可能的方法是,有一个备用过程,可以接管死去的父母的角色...... - 如果它可以再次接收步骤儿童的SIGCHLD信号!
Nic*_*son 16
不,绝对不可能.没有一些讨厌的竞争条件,它也无法实现.制作这些API的POSIX人永远不会创造具有固有竞争条件的东西,所以即使你没有被打扰,你的内核也不会很快得到它.
一个问题是pids被重用(它们是稀缺资源!),你也无法获得一个句柄或锁定; 这只是一个数字.因此,比方说,在代码中的某个位置,您有一个变量,您可以在其中放置要重新显示的进程的pid.然后你打电话make_this_a_child_of_me(thepid).那会发生什么?与此同时,其他进程可能已退出并thepid更改为引用其他进程!哎呀.如果没有make_this_a_child_of_me对unix处理进程的方式进行大规模重组,就无法提供API.
请注意,整个处理wait子pid正是为了防止这个问题:进程表中仍然存在僵尸进程,以防止其pid被重用.然后,父母可以通过其pid引用其子项,确信该过程不会退出并重新使用子pid.如果子进程退出,则其pid将保留,直到父进程捕获SIGCHLD或等待它.收到进程后,其pid会立即抓取,以便其他程序在fork时开始使用,但父级保证已经知道它.
对更新的响应:考虑一个更复杂的方案,其中进程被重新分配给它们的下一个祖先.显然,在每种情况下都无法做到这一点,因为你经常需要一种让孩子不认识的方法,以确保你避免僵尸.init非常好地履行了这个角色.因此,某个流程必须采用某种方式来指定它是否采用其孙子(或更低版本).这种设计的问题与第一种情况完全相同:你仍然会遇到竞争条件.
如果它再次由pid完成,那么祖父母就会暴露自己的竞争条件:只有父母能够获得一个pid,所以只有父母真正知道pid与哪个进程有关.因为祖父母无法获得,所以不能确定孙子进程没有从它想要采用的那个改变(或者取消,取决于假设的API如何工作).请记住,在负载很重的机器上,没有什么可以阻止一个进程从CPU上取下几分钟,并且整个负载可能在那段时间内发生了变化!不理想,但POSIX必须考虑到它.
最后,假设这个API不能通过pid工作,但通常会说,"将所有孙子送给我"或"将它们发送给init".如果在生成子进程后调用它,那么就像以前一样获得竞争条件.如果以前调用它,那么整个事情就没用了:你应该能够稍微重构你的应用程序以获得相同的行为.也就是说,如果你在开始产生儿童进程之前就已经知道谁应该是谁的父母,为什么你不能继续前进并在第一时间以正确的方式创建它们?管道和IPC确实能够完成所有必需的工作.