我知道: 1) waitpid用于等待孩子的死亡,然后收集孩子的SIGCHLD和退出状态等。2)当我们有一个SIGCHLD的信号处理程序时,我们做一些与清理孩子或其他东西相关的事情(直到程序员),然后做一个waitpid,这样孩子就不会变成僵尸然后返回。
现在,当我们执行fork/exec并子进程返回时,我们的程序中是否需要同时包含1和2?如果两者都有,则首先获取SIGCHLD,因此首先调用信号处理程序,从而成功调用它的waitpid,而不是父进程代码中的waitpid,如下所示:
my_signal_handler_for_sigchld
{
do something
tmp = waitpid(-1,NULL,0);
print tmp (which is the correct value of the child pid)
}
int main ()
{
sigaction(SIGCHLD, my_signal_handler_for_sigchld)
fork()
if (child) //do something, return
if parent // waitpid(child_pid, NULL,0); print value returned from this waitpid - it is -1
}如果有人能帮我理解这一点,我将不胜感激。
发布于 2012-01-24 02:11:45
如果你的意图是运行子进程,做一些事情,然后等待它完成,那么你真的不需要处理SIGCHLD。在这种情况下,您只需在准备好同步时调用waitpid。SIGCHLD唯一有用的是对子进程终止的异步通知,例如,如果您有一个交互式(或长期运行的守护进程)应用程序,该应用程序正在生成各种子进程,并且需要知道它们何时结束。然而,SIGCHLD在这方面也非常糟糕/丑陋,因为如果您使用创建子进程的库代码,您可能会捕捉到库子进程终止的事件,并干扰对它们的处理。信号处理程序本质上是进程全局的,并处理全局状态,这通常是一件坏事(Tm)。
下面是两种更好的方法,用于处理将要异步终止的子进程:
方法1(基于select/poll事件):确保您创建的每个子流程都有一个管道。它可以是它们的stdin/stdout/stderr,也可以是一个额外的虚拟fd。当子进程终止时,它的管道末端将关闭,您的主事件循环将检测该文件描述符上的活动。从它关闭的事实来看,您认出该子进程已死,并调用waitpid来获取僵尸进程。
方法2(基于线程):对于您创建的每个子进程,还要创建一个线程,该线程将立即调用子进程的pid上的waitpid。当waitpid成功返回时,使用您喜欢的线程同步原语让程序的其余部分知道该子线程已终止,或者在此等待线程终止之前处理您需要在此等待线程中执行的所有操作。
这两种方法都是模块化的并且对库友好(它们避免干扰可能使用子进程的代码或库代码的任何其他部分)。
发布于 2012-01-24 01:45:48
您需要调用等待的syscall,如waitpid或friends、-eg、wait4等-否则您可以调用zombie processes。
您可以处理SIGCHLD来通知某个孩子结束了(或停止了,等等)但您需要稍后等待它。
信号处理程序被限制为只能调用一小部分异步信号安全函数(有关更多信息,请参阅signal(7) )。好的建议是只在内部设置一个volatile sig_atomic_t标志,并在以后更安全的地方测试它。
https://stackoverflow.com/questions/8976004
复制相似问题