问题描述
你好,我是新来学习系统调用的人。我目前正在学习fork()和wait()系统调用。我知道fork()创建了一个新的子进程。让我感到困惑的是wait()调用。
到目前为止,这是我的理解:
(1)进程死亡时,它进入“僵尸状态”,即不释放其PID,而是等待其父进程确认子进程已死亡,然后释放PID
(2)因此,我们需要一种方法来弄清楚子进程何时结束,以便我们不会将任何进程置于僵尸状态。
我对以下事情感到困惑:
(1)在运行我在其中插入新子进程的C程序时,如果我未显式调用wait(),则子进程结束时是否在内部完成?因为您仍然可以在C中编写代码块,而不用wait()来运行fork(),并且看起来工作正常?
(2)wait()有什么作用?我知道它会返回已终止的子进程的PID,但这与释放已终止的进程的PID有什么帮助/相关?
对于如此幼稚的问题,我感到抱歉,但这是我真的很好奇的事情,我无法在网上找到任何好的资源!非常感谢您的帮助!
解决方法
wait
与防止僵尸状态无关。僵尸国家是你的朋友。
POSIX或多或少使您可以对pid
做两件事:用kill
发出信号,或用wait
/ waitpid
/ waittid
。
wait
系统调用主要用于等待进程退出或死于信号(尽管它们也可以用于等待其他进程状态更改,例如子进程停止或子进程从中醒来)正在停止)。
其次,它们是要获得退出/死亡状态,从而释放(僵化)pid
。
在您用pid
/ wait
/ waitpid
释放waittid
之前,您可以继续鞭打pid
并要求其死亡({{ 1}})或其他信号(kill(pid,SIGTERM);
以外的信号),您可以放心SIGKILL
代表您已经分叉的过程,并且不会意外杀死其他人的过程。
但是一旦您通过pid
插入僵化的pid
而获得了pid,则该pid将不再是您的pid,并且可能需要另一个进程(通常会在一段时间后发生,例如{{1}系统中的}通常会先递增,然后环绕arround。
这就是为什么自动等待不是一个好主意的原因(在某些情况下不是这样,然后您可以使用wait
在全局范围内实现),为什么(短暂的)僵尸状态是您的朋友。他们会为您保持孩子pid
的稳定,直到您准备释放它为止。
如果您退出而没有释放任何孩子的signal(SIGCHLD,SIG_IGN);
,那么您就不必担心僵尸孩子了-您的孩子进程将被重新初始化为{{1} }在他们死后为您服务。
调用fork()
时,将以其为父进程创建一个新进程。当子进程通过调用exit()
完成运行时,其进程描述符仍保留在内核内存中。作为父级,您有责任收集其退出代码,这是通过调用wait()
syscall来完成的。 wait()
阻止父进程,直到其子进程之一结束。
僵尸进程是给其退出代码从未被其父代收集的进程指定的名称。
关于您的第一个问题-wait()
不会自动调用,因为如果存在,僵尸进程将不存在。作为程序员,这是您的责任。如您所提到的,忽略对wait()
的呼叫仍然可以进行-但这是一种不良做法。