Строки 71–76 обрабатывают любую другую ошибку, выводя соответствующее сообщение об ошибке.
81 /* main --- установка связанных с порожденными процессами сведений и сигналов, создание порожденных процессов */
82
83 int main(int argc, char **argv)
84 {
85 struct sigaction sa;
86 sigset_t childset, emptyset;
87 int i;
88
89 for (i = 0; i < nkids; i++)
90 kids[i] = NOT_USED;
91
92 sigemptyset(∅);
93
94 sa.sa_flags =
SA_NOCLDSTOP;
95 sa.sa_handler = childhandler;
96 sigfillset(&sa.sa_mask); /* блокировать все при вызове обработчика */
97 sigaction(SIGCHLD, &sa, NULL);
98
99 sigemptyset(&childset);
100 sigaddset(&childset, SIGCHLD);
101
102 sigprocmask(SIG_SETMASK, &childset, NULL); /* блокировать его в коде main */
103
104 for (nkids = 0; nkids < 5; nkids++) {
105 if ((kids[nkids] = fdrk()) == 0) {
106 sleep(3);
107 _exit(0);
108 }
109 }
110
111 sleep(5); /* дать потомкам возможность завершения */
112
113 printf("waiting for signal\n");
114 sigsuspend(∅);
115
116 return 0;
117 }
Строки 89–90 инициализируют kids
emptyset
. Строки 94–97 настраивают и устанавливают обработчик сигнала для SIGCHLD
. Обратите внимание на использование в строке 94 SA_NOCLDSTOP
, тогда как строка 96 блокирует все сигналы при вызове обработчика.Строки 99–100 создают набор сигналов, представляющих SIGCHLD
Строки 104–109 создают пять порожденных процессов, каждый из которых засыпает на три секунды. По ходу дела они обновляют массив kids
nkids
.Строка 111 дает затем потомкам шанс завершиться, заснув на еще больший промежуток времени. (Это не
Наконец, строки 113–114 выводят сообщение и приостанавливаются, заменив маску сигналов процесса, блокирующую SIGCHLD
SIGCHLD
, что в свою очередь вызывает запуск обработчика сигнала. Вот что происходит:$ ch10-reap1
waiting for signal
Entered childhandler
reaped process 23937
reaped process 23938
reaped process 23939
reaped process 23940
reaped process 23941
Exited childhandler
Обработчик сигнала собирает сведения о потомках за один проход.
Следующая программа, ch10-reap2.c
ch10-reap1.c
. Разница в том, что она допускает появление сигнала SIGCHLD
в любое время. Такое поведение увеличивает шанс получения более одного SIGCHLD
, но 1 /* ch10-reap2.c — демонстрирует управление SIGCHLD, один сигнал на потомка */
2
/* ...не изменившийся код пропущен... */
12
13 pid_t kids[MAX_KIDS];
14 size_t nkids = 0;
15 size_t kidsleft = 0; /* <<< Добавлено */
16
/* ...не изменившийся код пропущен... */
41
42 /* childhandler --- перехват SIGCHLD, опрос всех доступных потомков */
43
44 void childhandler(int sig)
45 {
46 int status, ret;
47 int i;
48 char buf[100];
49 static const char entered[] = "Entered childhandler\n";
50 static const char exited[] = "Exited childhandler\n";
51
52 write(1, entered, strlen(entered));
53 for (i = 0; i < nkids; i++) {