为什么我们需要一个wait()系统调用?

时间:2020-09-29 06:51:47

标签: linux process operating-system waitpid

你好,我是新来学习系统调用的人。我目前正在学习fork()和wait()系统调用。我知道fork()创建了一个新的子进程。让我感到困惑的是wait()调用。
到目前为止,这是我的理解:
(1)进程死亡时,它进入“僵尸状态”,即不释放其PID,而是等待其父进程确认子进程已死亡,然后释放PID
(2)因此,我们需要一种方法来弄清楚子进程何时结束,以便我们不会将任何进程置于僵尸状态。

我对以下事情感到困惑:
(1)在运行我在其中插入新子进程的C程序时,如果我未显式调用wait(),则子进程结束时是否在内部完成?因为您仍然可以在C中编写代码块,而不用wait()来运行fork(),并且看起来工作正常?
(2)wait()有什么作用?我知道它会返回已终止的子进程的PID,但这与释放已终止的进程的PID有什么帮助/相关?

对于如此幼稚的问题,我感到抱歉,但这是我真的很好奇的事情,我无法在网上找到任何好的资源!非常感谢您的帮助!

2 个答案:

答案 0 :(得分:3)

wait与防止僵尸状态无关。僵尸国家是你的朋友。

POSIX或多或少使您可以对pid做两件事:用kill发出信号,或用wait / waitpid / waittid

wait系统调用主要用于等待进程退出或死于信号(尽管它们也可以用于等待其他进程状态更改,例如子进程停止或子进程从中醒来)正在停止)。

其次,它们是要获得退出/死亡状态,从而释放(僵化)pid

在您用pid / wait / waitpid释放waittid之前,您可以继续鞭打pid并要求其死亡({{ 1}})或其他信号(kill(pid,SIGTERM);以外的信号),您可以放心SIGKILL代表您已经分叉的过程,并且不会意外杀死其他人的过程。< / p>

但是一旦您通过pid插入僵化的pid而获得了pid,则该pid将不再是您的pid,并且可能需要另一个进程(通常会在一段时间后发生,例如{{1}系统中的}通常会先递增,然后环绕arround。

这就是为什么自动等待不是一个好主意的原因(在某些情况下不是这样,然后您可以使用wait在全局范围内实现),为什么(短暂的)僵尸状态是您的朋友。他们会为您保持孩子pid的稳定,直到您准备释放它为止。

如果您退出而没有释放任何孩子的signal(SIGCHLD,SIG_IGN);,那么您就不必担心僵尸孩子了-您的孩子进程将被重新初始化为{{1} }在他们死后为您服务。

答案 1 :(得分:1)

调用fork()时,将以其为父进程创建一个新进程。当子进程通过调用exit()完成运行时,其进程描述符仍保留在内核内存中。作为父级,您有责任收集其退出代码,这是通过调用wait() syscall来完成的。 wait()阻止父进程,直到其子进程之一结束。

僵尸进程是给其退出代码从未被其父代收集的进程指定的名称。

关于您的第一个问题-wait()不会自动调用,因为如果存在,僵尸进程将不存在。作为程序员,这是您的责任。如您所提到的,忽略对wait()的呼叫仍然可以进行-但这是一种不良做法。

this linkthis link都很好。