C语言 是否有可能通过一个进程?

2j4z5cfb  于 2023-01-20  发布在  其他
关注(0)|答案(4)|浏览(151)

进程A fork() s进程B。
进程A终止,因此init采用B。
看门狗创建进程C。
C是否有可能从init中采用B?

    • 更新**:

或者,如果C在A死亡之前被创建,而init没有成为B的中间父节点,那么C是否有可能直接采用B(当A死亡时)?

    • 更新-1:**

此外,我将感谢任何评论,为什么有可能通过一个过程的方式,我所描述的将是一件坏事或难以不可能实施。

    • 更新-2**-用例(父项和子项指流程):

我有一个应用程序,它使用一个父节点来管理一大堆子节点,而这些子节点依赖于父节点的管理功能,父节点依赖于收到子节点终止的通知,这是通过接收相关的SIGCHLD信号来完成的。
如果父节点本身由于某种意外(包括segfault)而死亡,我需要重新启动整个"家族",因为现在不可能在子节点终止时触发某些操作(这也可能是由于segfault)。
在这种情况下,我需要关闭所有子进程,并重新启动整个系统。
避免这种情况的一个可能的方法是,在适当的位置有一个备用进程,它可以接管死父进程的角色... -如果它可以再次接收到步骤子进程的SIGCHLD信号!

z18hc3ub

z18hc3ub1#

不,绝对不可能。如果没有一些讨厌的竞争条件,它也不可能实现。制作这些API的POSIX人员永远不会创建带有固有竞争条件的东西,所以即使你不担心,你的内核也不会很快得到它。
一个问题是pid会被重用(它们是稀缺资源!),而且你也不能在pid上获得句柄或锁;它只是一个数字,比如说,在代码的某个地方,你有一个变量,你把你想重定父级的进程的pid放在那里,然后你调用make_this_a_child_of_me(thepid),然后会发生什么?同时,另一个进程可能已退出,并且thepid已更改为引用其他某个进程!哎呀,不能有'这是一种提供make_this_a_child_of_me API而不对unix处理进程的方式进行大规模重组的方法。
请注意,在子PID上使用wait的整个处理过程就是为了防止这个问题:僵尸进程仍然存在于进程表中,以防止其pid被重用。父进程可以通过其pid引用其子进程,确信该进程不会退出并重用子进程pid。如果子进程退出,其pid将被保留,直到父进程捕获SIGCHLD或等待SIGCHLD。一旦进程被捕获,它的pid可供其他程序在派生时立即获取以开始使用,但父进程肯定已经知道它。

对最新情况的答复:考虑一个更复杂的方案,其中进程被重为父进程。显然,这不是在所有情况下都能做到的,因为您经常需要一种方法来取消子进程的所有权,以确保避免僵尸进程。init很好地满足了这个角色。因此,必须有某种方法来指定进程是否打算采用,它的孙子(或更低)。这个设计的问题与第一种情况完全相同:你仍然会遇到竞态条件。

如果pid再次执行此操作,则祖父将自己暴露于争用条件:只有父进程能够获取pid,因此只有父进程真正知道pid属于哪个进程。因为祖父进程不能获取,所以它不能确定孙子进程没有改变它打算采用的进程(或者不承认,这取决于假设的API如何工作)记住,在负载很重的机器上,没有什么可以阻止进程离开CPU几分钟,整个负载可能会在这段时间内发生变化!这不太理想,但POSIX必须考虑到这一点。
最后,假设这个API不通过pid工作,而只是一般地说,“send all sugrands to me”或“send them to init”.如果在子进程产生之后调用它,那么你会得到和以前一样的竞态条件.如果在之前调用它,那么整个过程都是无用的:你应该能够重构你的应用程序来获得相同的行为。也就是说,如果你在开始生成子进程之前就知道谁应该是谁的父进程,为什么你不能直接开始并在第一时间以正确的方式创建它们呢?管道和IPC确实能够完成所有需要的工作。

jgwigjjp

jgwigjjp2#

不,你不可能以你所描述的方式强制实施再养育。

gab6jxml

gab6jxml3#

我不知道有什么好的方法可以做到这一点,但使用它的一个原因是,正在运行的流程可以独立运行,也可以向父流程添加功能。孩子,但不是父母。即将出生的孩子会向父母发出信号。父母会收养一旦成为父进程的一部分,父进程/子进程就能够对事件做出React,而当单独存在时,两者都不能对事件做出React。
这种对接行为可以被编码到应用程序中,但我不知道如何实时实现。还有其他方法可以实现同样的功能。可以接受停靠子应用程序的父应用程序可以用以前不知道的新方法扩展其功能。

llmtgqce

llmtgqce4#

虽然最初的问题是用unix标记的,但在linux上有一种方法可以实现这一点,所以值得一提。这可以通过使用subreaper进程来实现。当一个进程的父进程时,它将被最近的subreaper祖先或init所采用。因此,在您的示例中,您将通过prctl(PR_SET_CHILD_SUBREAPER)将进程C设置为subreaper,并在进程A死亡时生成进程A。C将采用流程B
Linux上的一个替代方案是在一个单独的PID名称空间中产生C,使其成为PID名称空间的init进程,因此可以在A死亡时采用A的子进程。

相关问题