在父进程恢复执行之前等待所有子进程 UNIX

Posted

技术标签:

【中文标题】在父进程恢复执行之前等待所有子进程 UNIX【英文标题】:Waiting for all child processes before parent resumes execution UNIX 【发布时间】:2010-12-03 09:55:10 【问题描述】:

在我的程序中,我在有限的 while 循环中分叉(并行)子进程,并对每个子进程执行 exec。我希望父进程仅在所有子进程终止后才能恢复执行(此 while 循环之后的点)。我该怎么做?

我尝试了几种方法。在一种方法中,我在 while 循环之后让父级暂停,并仅在 waitpid 返回错误 ECHILD(没有子级剩余)时从 SIGCHLD 处理程序发送一些条件,但我在这种方法中面临的问题甚至在父级完成所有进程的分叉之前,retStat 变为-1

    void sigchld_handler(int signo) 
        pid_t pid;
        while((pid= waitpid(-1,NULL,WNOHANG)) > 0);
        if(errno == ECHILD) 
            retStat = -1;
        
    

    **//parent process code**
    retStat = 1;
    while(some condition) 
       do fork(and exec);
    

    while(retStat > 0)
        pause();
//This is the point where I want execution to resumed only when all children have finished

【问题讨论】:

【参考方案1】:

我认为您应该使用@987654321@ 电话。它允许你等待“任何子进程”,所以如果你这样做了正确的次数,你应该是黄金。

如果失败(不确定保证),您可以在循环中执行蛮力方法,在您的每个子 PID 上使用 NOHANG 选项执行 waitpid(),然后延迟一段时间在重做之前。

【讨论】:

请看代码,我做的和你说的一模一样。 @aditya:呃,不,我的建议是按照 jborque 的建议去做,我没有说任何关于使用信号处理程序的内容。【参考方案2】:

与其在信号处理程序中调用waitpid,不如在你按如下方式分叉所有进程之后创建一个循环:

while (pid = waitpid(-1, NULL, 0)) 
   if (errno == ECHILD) 
      break;
   

程序应该在循环中挂起,直到没有更多的孩子。然后它会掉出来,程序将继续。作为额外的奖励,循环将在孩子们运行时阻塞waitpid,因此您在等待时不需要繁忙的循环。

您也可以使用wait(NULL),它应该等同于waitpid(-1, NULL, 0)。如果在 SIGCHLD 中你不需要做任何其他事情,你可以将其设置为 SIG_IGN。

【讨论】:

我需要给 WNOHANG 选项,因为如果有很多孩子几乎同时传递 SIGCHLD 信号,并且由于信号在 UNIX 中没有排队,如果我使用 0,那么我将能够只捕获一个信号,就会留下僵尸。 补充一点,-1 将检查任何子 pid(为了清楚起见,也可以使用 WAIT_ANY)。 @aditya:僵尸进程正等着你调用 wait()(或 wait_pid())。只要你这样做,它们就会消失,无论你是否捕捉到信号。所以 fork() 循环之后的 wait() 循环会清除所有的僵尸。 同意 -- 如果您使用的是wait/waitpid,那么您不需要自己处理SIGCHLD

以上是关于在父进程恢复执行之前等待所有子进程 UNIX的主要内容,如果未能解决你的问题,请参考以下文章

Unix C

如何在父进程终止后终止所有子进程?

php多进程编程实现与优化

fork 与 vfork

使用管道在父进程和子进程之间进行通信的问题

UNIX环境高级编程第八章二