Fork () с несколькими детьми и с ожиданием, пока все они закончат - PullRequest
1 голос
/ 18 мая 2019

Я хочу создать программу на C, где я использую 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;
    }

Если бы кто-то мог исправить мой код или написать лучшее решение этой проблемы, я был бы очень благодарен!

1 Ответ

0 голосов
/ 18 мая 2019

Если вы хотите, чтобы все дети работали параллельно, вы должны подождать после запуска всех детей. В противном случае вы начинаете ребенка, ждете, пока он закончится, начинаете новый, ждете, пока он закончится, запускаете третий, ждете, пока закончится третий, и так далее ...

Итак, что вы обычно хотите, это запустить все дочерние элементы и поместить все 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
 }

Естественно, это не полный пример, который подходит для любой ситуации. Иногда вы должны сказать детям, когда они должны выйти. В других случаях дети не запускаются / не останавливаются за один раз, и вам приходится играть с асинхронными событиями и т. Д. ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...