Форк и waitpid в C

У меня есть этот кусок кода, может быть, я что-то упустил:

const int NPROCESSES = 32;   
pid_t pids[128];

for (int i = 0; i < NPROCESSES;i ++) {
   pids[i] = fork();
   if (!pids[i]) {  
       /*... other code ...*/
       exit(0);
   }
}

for (int i = 0; i < NPROCESSES; i++)
    waitpid(pids[i], 0, 0);

Программа должна запустить 32 процесса и дождаться завершения всех процессов. Но иногда программа блокируется дочерними процессами зомби. Где я не прав?

1 ответ

С помощью:

waitpid(pids[i], 0, 0);

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

В результате, если один из дочерних элементов блокирует или задерживает по какой-либо причине, а другой дочерний элемент, созданный позднее, уже завершил (и вызвал exit()), последний останется в состоянии зомби, пока родитель не пожнет первого ребенка первым.

Так, если, например, процессу, созданному на первой итерации цикла, требуется 1 минута для завершения, а остальные 31 процесс завершен за 1 секунду, вы сможете наблюдать 31 процесс зомби, ожидающий, когда его родитель будет пожинать, который (родитель) будет ждать, чтобы сначала пожать этот задержанный процесс.

Чтобы изменить это поведение, родитель может использовать:

waitpid(-1, NULL, 0);

вместо. Значение, равное -1 в первом аргументе waitpid() означает, что он будет пожинать любой из дочерних процессов, цитируя man 2 waitpid:

Значение pid может быть:

< -1

это означает ожидание любого дочернего процесса, чей идентификатор группы процессов равен абсолютному значению pid.

-1

смысл ждать любого дочернего процесса.

0

Это означает ожидание любого дочернего процесса, чей идентификатор группы процессов равен идентификатору вызывающего процесса.

> 0

что означает ожидание ребенка, чей идентификатор процесса равен значению pid.

Кроме того, вы можете просто использовать:

wait(NULL);

который так же, как waitpid(-1, NULL, 0),

Другие вопросы по тегам