如何让父母等待所有子进程完成?

Posted

技术标签:

【中文标题】如何让父母等待所有子进程完成?【英文标题】:How to make parent wait for all child processes to finish? 【发布时间】:2013-10-28 00:15:02 【问题描述】:

我希望有人能阐明如何让父进程等待 ALL 子进程完成,然后再继续分叉。我有想要运行的清理代码,但子进程需要在这发生之前返回。

for (int id=0; id<n; id++) 
  if (fork()==0) 
    // Child
    exit(0);      
   else 
    // Parent
    ...
  
  ...

【问题讨论】:

如果您关心哪个孩子退出以及何时退出,您会发现从所有这些分叉返回的 pid 对您的任务特别有用。否则wait()n 次。 【参考方案1】:
pid_t child_pid, wpid;
int status = 0;

//Father code (before child processes start)

for (int id=0; id<n; id++) 
    if ((child_pid = fork()) == 0) 
        //child code
        exit(0);
    


while ((wpid = wait(&status)) > 0); // this way, the father waits for all the child processes 

//Father code (After all child processes end)

wait 等待一个 子进程终止,并返回该子进程的pid。出错时(例如,当没有子进程时),返回-1。所以,基本上,代码一直在等待子进程完成,直到出现waiting 错误,然后你就知道它们都完成了。

【讨论】:

我想知道假设“wait() 期间的错误”等于“没有更多的孩子等待”是否安全。 man 2 wait 说:ECHIILD (for wait()) The calling process does not have any unwaited-for children. 我想你可以 #include &lt;errno.h&gt; 并在此期间使用它。【参考方案2】:

POSIX 定义了一个函数:wait(NULL);。它是waitpid(-1, NULL, 0); 的简写,它将暂停调用进程的执行,直到任何一个子进程退出。 这里,waitpid 的第一个参数表示等待任何子进程结束。

在您的情况下,让父级从您的 else 分支中调用它。

【讨论】:

感谢您的回复。我在非子部分添加了等待(NULL),程序只是挂起,子进程甚至不执行?? 哦,这不是 wait() 造成的错误。你应该把你的完整代码给我调试一下。你的代码太简单了,只是一个模型。 wait 的联机帮助页说它等待 一个 子节点终止。正如上面提到的@WhozCraig,您需要waitn 次。 这里更详细地解释了 wait 调用:man7.org/linux/man-pages/man2/waitpid.2.html 我使用while(wait(NULL) &gt; 0);,以便进程等待所有其子进程终止。【参考方案3】:

像这样使用 waitpid():

pid_t childPid;  // the child process that the execution will soon run inside of. 
childPid = fork();

if(childPid == 0)  // fork succeeded 
   
   // Do something   
   exit(0); 


else if(childPid < 0)  // fork failed 
    
   // log the error


else  // Main (parent) process after fork succeeds 
    
    int returnStatus;    
    waitpid(childPid, &returnStatus, 0);  // Parent process waits here for child to terminate.

    if (returnStatus == 0)  // Verify child process terminated without error.  
    
       printf("The child process terminated normally.");    
    

    if (returnStatus == 1)      
    
       printf("The child process terminated with an error!.");    
    

【讨论】:

这不会等到所有孩子都完成一个孩子 childPid。如果有更多进程,这是行不通的。 当然,如果您从单个父进程创建多个线程,则必须相应地修改此示例。提供一个包含多个分叉的示例会使我的答案看起来令人困惑。 你会如何修改这个代码让父母等待所有孩子完成? @JasonEnochs 我认为修改多个分叉的示例并非易事。如果您的代码只是“循环”n 次(将 waitpid 调用放在分叉循环中),那么我认为我们会得到子进程的串行执行,这可能是不希望的。下面@adrisons 的答案看起来不错。【参考方案4】:

只需使用:

while(wait(NULL) > 0);

这确保您等待所有子进程,并且只有当所有子进程都返回时,您才转到下一条指令。

【讨论】:

以上是关于如何让父母等待所有子进程完成?的主要内容,如果未能解决你的问题,请参考以下文章

尽管收获,父母不会等待子进程完成

如何让子进程等待其兄弟?

父进程工作直到子进程完成

等待进程直到所有子进程完成? [复制]

ruby 等待所有分叉的子进程完成

主进程或者主线程是否会等待子线程或子进程的问题