【问题标题】:Waiting for all child processes before parent resumes execution UNIX在父进程恢复执行之前等待所有子进程 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

【问题讨论】:

    标签: c unix fork


    【解决方案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
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-13
    相关资源
    最近更新 更多