Форк и 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)
,