Ожидание всех дочерних процессов, прежде чем родитель возобновит выполнение UNIX - PullRequest
12 голосов
/ 02 октября 2009

В моей программе я разветвляю (параллельно) дочерние процессы в конечном цикле while и выполняю exec для каждого из них. Я хочу, чтобы родительский процесс возобновил выполнение (точка после этого цикла while) только после завершения всех дочерних процессов. Как мне это сделать?

Я пробовал несколько подходов. В одном из подходов я сделал родительскую паузу после цикла while и отправил некоторое условие из обработчика SIGCHLD только тогда, когда waitpid возвратил ошибку ECHILD (дочерний элемент отсутствует), но проблема, с которой я сталкиваюсь в этом подходе, заключается в том, что даже когда родительский процесс завершил разветвление всех процессов, 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

Ответы [ 2 ]

21 голосов
/ 02 октября 2009

Вместо вызова waitpid в обработчике сигналов, почему бы не создать цикл после того, как вы разветвили все процессы следующим образом:

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

Программа должна висеть в цикле, пока не останется детей. Тогда он выпадет и программа продолжится. В качестве дополнительного бонуса, цикл будет блокироваться на waitpid, пока дети бегут, поэтому вам не нужен цикл занят, пока вы ждете.

Вы также можете использовать wait(NULL), что должно быть эквивалентно waitpid(-1, NULL, 0). Если вам больше ничего не нужно делать в SIGCHLD, вы можете установить для него значение SIG_IGN.

0 голосов
/ 02 октября 2009

Я думаю, что вы должны использовать <a href="http://linux.die.net/man/2/waitpid" rel="nofollow noreferrer">waitpid()</a> вызов. Это позволяет вам ждать «любого дочернего процесса», поэтому, если вы делаете это нужное количество раз, вы должны быть золотым.

Если это не удастся (не уверен насчет гарантий), вы можете использовать метод грубой силы, сидя в цикле, выполнив waitpid() с опцией NOHANG для каждого из ваших дочерних PID, а затем отложив для пока, прежде чем сделать это снова.

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