Чтобы помочь себе понять, включайте PID и PPID в каждое заявление printf()
.Кроме того, захватывайте и сообщайте значение (PID мертвого ребенка), возвращаемое wait()
каждый раз, когда оно вызывается;Вы можете решить, следует ли сообщать status
или нет, но инициализировать его равным нулю в случае (если когда) вызовы wait()
не будут выполнены, потому что нет дочернего элемента.Потом дети продолжают, прежде чем родитель возвращается из вызовов wait()
.
Или, лучше, напишите функцию регистрации, которая может обработать детали для вас.Например, рассмотрим следующий код:
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
static void print_info(const char *tag, int corpse, int status, int child)
{
int pid = getpid();
int ppid = getppid();
printf("PID %5d, PPID %5d: %s (corpse: %5d, status 0x%.4X), child %5d\n",
pid, ppid, tag, corpse, status, child);
}
int main(void)
{
int pid = getpid();
int ppid = getppid();
printf("Initial PID %5d, PPID %5d:\n", pid, ppid);
int status = 0;
int child = fork();
int corpse = wait(&status);
print_info("a", corpse, status, child);
child = fork();
corpse = wait(&status);
print_info("b", corpse, status, child);
child = fork();
corpse = wait(&status);
print_info("c", corpse, status, child);
child = fork();
corpse = wait(&status);
print_info("d", corpse, status, child);
return 0;
}
Пример прогона дает мне:
Initial PID 7357, PPID 20754:
PID 7358, PPID 7357: a (corpse: -1, status 0x0000), child 0
PID 7359, PPID 7358: b (corpse: -1, status 0x0000), child 0
PID 7360, PPID 7359: c (corpse: -1, status 0x0000), child 0
PID 7361, PPID 7360: d (corpse: -1, status 0x0000), child 0
PID 7360, PPID 7359: d (corpse: 7361, status 0x0000), child 7361
PID 7359, PPID 7358: c (corpse: 7360, status 0x0000), child 7360
PID 7362, PPID 7359: d (corpse: -1, status 0x0000), child 0
PID 7359, PPID 7358: d (corpse: 7362, status 0x0000), child 7362
PID 7358, PPID 7357: b (corpse: 7359, status 0x0000), child 7359
PID 7363, PPID 7358: c (corpse: -1, status 0x0000), child 0
PID 7364, PPID 7363: d (corpse: -1, status 0x0000), child 0
PID 7363, PPID 7358: d (corpse: 7364, status 0x0000), child 7364
PID 7358, PPID 7357: c (corpse: 7363, status 0x0000), child 7363
PID 7365, PPID 7358: d (corpse: -1, status 0x0000), child 0
PID 7358, PPID 7357: d (corpse: 7365, status 0x0000), child 7365
PID 7357, PPID 20754: a (corpse: 7358, status 0x0000), child 7358
PID 7366, PPID 7357: b (corpse: -1, status 0x0000), child 0
PID 7367, PPID 7366: c (corpse: -1, status 0x0000), child 0
PID 7368, PPID 7367: d (corpse: -1, status 0x0000), child 0
PID 7367, PPID 7366: d (corpse: 7368, status 0x0000), child 7368
PID 7366, PPID 7357: c (corpse: 7367, status 0x0000), child 7367
PID 7369, PPID 7366: d (corpse: -1, status 0x0000), child 0
PID 7366, PPID 7357: d (corpse: 7369, status 0x0000), child 7369
PID 7357, PPID 20754: b (corpse: 7366, status 0x0000), child 7366
PID 7370, PPID 7357: c (corpse: -1, status 0x0000), child 0
PID 7371, PPID 7370: d (corpse: -1, status 0x0000), child 0
PID 7370, PPID 7357: d (corpse: 7371, status 0x0000), child 7371
PID 7357, PPID 20754: c (corpse: 7370, status 0x0000), child 7370
PID 7372, PPID 7357: d (corpse: -1, status 0x0000), child 0
PID 7357, PPID 20754: d (corpse: 7372, status 0x0000), child 7372
Вы можете просматривать данные, видя, что их 2 4 процессы для вызовов 4 fork()
(после каждого вызова есть 2 процесса, в которых до этого был 1 процесс, поэтому после одного вызова есть 2 процесса; после 2 вызовов, 4 процесса и т. д.) и что дочерний процессзавершает работу, прежде чем родитель продолжит работу (поэтому в этом примере PID 7357 является последним для печати тега a
, тега b
, тега c
и тега d
).
Каждый раз, когда у вас возникают трудности с отслеживанием дерева процессов, используйте метод печати, подобный этому, чтобы помочь вам лучше понять, что происходит.