首页 > 解决方案 > Fork() 有多个孩子并等待所有孩子完成

问题描述

我想在 C 中创建一个程序,我使用 fork() 创建多个子级,然后等待所有子级完成并执行父级代码(仅一次)。我尝试使用 for 循环和两个 fork,但我有一个问题:父代码最后没有运行,或者子代码没有并行运行。

//Number of processes I want to create
int processes = 6;

pid_t *main_fork = fork();

    if(main_fork ==0){

      for(int i=0;i<processes;i++){
        pid_t *child_fork = fork();

        if(child_fork ==0){

           // child code
           exit(0);
        }
       else if(child_fork >0){
        //And here is the problem, with the wait: children don't 
        //run parallel and if I delete it, the main parent code doesn't run 
         wait(NULL);
       }else{
        // Child fork failed
         printf("fork() failed!\n");
         return 1;
       }
      }
    }else if(main_fork >0){

      wait(NULL);
      //Main parent code - here I want to do something only once after all 
      //children are done

    }else{
      // Main fork failed
      printf("fork() failed!\n");
      return 1;
    }

如果有人可以修复我的代码,或者为这个问题写一个更好的解决方案,我将不胜感激!

标签: cfork

解决方案


如果你想让所有的孩子并行运行,你必须在所有的孩子都启动后等待。否则你开始一个孩子,等待它完成,开始一个新的,等待那个完成,开始第三个,等待第三个完成,等等......

所以你通常想要做的是启动所有的孩子并将所有的pid_t放在一个数组中,当你完成后你可以调用wait()每个pid_t

这是适合您的情况的简单且足够好的解决方案。

这是您可以解决问题的示例代码:

pid_t children[processes];

for(int i=0; i<processes; i++)
  {
    pid_t child = fork();

    if(child == 0)
      {
        // child code
         ....
        // We call _exit() rather than exit() since we don't want to clean up
        // data structures inherited from parent
        _exit(0);
      }
    else if (child == -1)
      {
         // Child fork failed
         fprintf(stderr, "myprog: fork failed, %s", strerror(errno));

         // Do real cleanup on failure is to complicated for this example, so we
         // just exit           
         exit(EXIT_FAILURE);
      }
    children[i] = child;
  }
// Do something if you want to do something before you expect the children to exit
.... 

for(int i=0; i<processes; i++)
  {
    pid_t child = children[i];

    int status;
    waitpid(child, &status, );

    // Do something with status
 }

当然,这不是一个适合任何情况的完整示例。有时你必须告诉孩子们什么时候应该离开。其他时候,孩子们不会一次启动/停止,你必须玩异步事件,等等......


推荐阅读