25

进程 Afork()的进程 B。

过程 A 死亡,因此init采用 B。

看门狗创建进程 C。

C 是否有可能从 中采用 B init


更新

或者,如果 C 是在 A 死之前创建的,而不init成为 B 的中间父级,甚至有可能让 C 直接采用 B(当 A 死时)?


更新 1:

此外,如果有任何意见说明为什么有可能采用我所描述的方式将是一件坏事或难以实施,我将不胜感激。


Update-2 - 用例(父母和孩子指的是流程):

我有一个应用程序使用父母来管理一大群孩子,这依赖于父母的管理设施。为了完成其工作,父母依赖于收到孩子终止的通知,这是通过接收相关SIGCHLD信号来完成的。

如果父母本身因某种事故(包括段错误)而死亡,我需要重新启动整个“家庭”,因为现在不可能在孩子终止时触发某些事情(这也可能是由于段错误)。

在这种情况下,我需要关闭所有孩子并重新启动整个系统。

避免这种情况的一种可能方法是建立一个备用进程,它可以接管死去的父母的角色...... - 如果它可以再次接收到继子女的SIGCHLD信号!

4

3 回答 3

16

不,绝对不可能。如果没有一些讨厌的竞争条件,它也无法实现。制作这些 API 的 POSIX 人员永远不会创建具有固有竞争条件的东西,所以即使您不介意,您的内核也不会很快得到它。

一个问题是 pid 被重复使用(它们是一种稀缺资源!),而且您也无法获得句柄或锁定一个;这只是一个数字。因此,比如说,在您的代码中的某处,您有一个变量,您可以在其中放置要重新设置的进程的 pid。然后你打电话make_this_a_child_of_me(thepid)。那时会发生什么?与此同时,其他进程可能已经退出并thepid更改为引用其他进程!哎呀。make_this_a_child_of_me如果不对unix 处理进程的方式进行大规模重组,就无法提供API。

请注意,对子 pid 进行 ing 的整个处理wait正是为了防止这个问题:进程表中仍然存在僵尸进程,以防止其 pid 被重用。然后,父进程可以通过它的 pid 引用它的子进程,确信进程不会退出并让子进程 pid 重用。如果子进程退出,它的 pid 将被保留,直到父进程捕获 SIGCHLD 或等待它。一旦进程被收割,它的 pid 立即可供其他程序在它们分叉时开始使用,但父进程保证已经知道它。

对更新的响应:考虑一个更复杂的方案,其中进程被重新分配给它们的下一个祖先。显然,这不可能在所有情况下都这样做,因为您经常想要一种与孩子断绝关系的方式,以确保您避免僵尸。init 很好地完成了这个角色。因此,流程必须通过某种方式来指定它打算收养或不收养其孙辈(或更低)。这种设计的问题与第一种情况完全相同:您仍然会遇到竞争条件。

如果再次由 pid 完成,则祖父母将自己暴露于竞争条件:只有父母能够获得 pid,因此只有父母真正知道 pid 与哪个进程一起使用。因为祖父母不能收割,所以不能确定孙进程没有改变它打算采用的进程(或不承认,取决于假设的 API 的工作方式)。请记住,在负载很重的机器上,没有什么可以阻止进程在几分钟内从 CPU 中取出,而整个负载可能在这段时间内发生了变化!不理想,但 POSIX 必须考虑到这一点。

最后,假设这个 API 不能通过 pid 工作,而只是一般地说,“将所有孙子发送给我”或“将它们发送给 init”。如果在子进程生成后调用它,那么您会像以前一样获得竞争条件。如果之前调用过它,那么整个事情就没用了:您应该能够稍微重构您的应用程序以获得相同的行为。也就是说,如果您在开始生成子进程之前就知道谁应该是谁的父进程,那么为什么不能一开始就以正确的方式创建它们呢?Pipes 和 IPC 确实能够完成所有必需的工作。

于 2012-05-11T11:00:01.287 回答
8

不,您无法按照您所描述的方式强制执行 Reparenting。

于 2012-05-09T16:13:21.740 回答
0

我不知道这样做的好方法,但拥有它的一个原因是运行的进程可以独立运行或向父进程添加功能。收养将作为事件的结果发生,由(尚未)孩子知道,但父母不知道。即将出生的孩子会向父母发送信号。父母会收养(或不收养)孩子。一旦成为父进程的一部分,父/子进程将能够对事件做出反应,而当单独站立时,它们都无法对事件做出反应。

这种对接行为可以编码到应用程序中,但我不知道如何实时进行。还有其他方法可以实现相同的功能。可以接受对接孩子的父母可以以父母以前不知道的新颖方式扩展其功能。

于 2020-11-16T17:13:04.310 回答