Роббинс Арнольд
Шрифт:
Другой возможностью, дающей такой же результат, является использование флага
SA_NOCLDWAIТ
. В коде: /* Старый стиль: */ /* Новый стиль: */
signal(SIGCHLD, SIG_IGN); struct sigaction sa;
sa.sa_handler = SIG_IGN;
sa.sa_flags = SA_NOCLDWAIT;
sigemptyset(&sa.sa_mask);
sigaction(SIGCHLD, &sa, NULL);
10.8.3.2. Снисходительные родители: минимальный надзор
В качестве альтернативы можно беспокоиться лишь о завершении потомка и не интересоваться простыми изменениями состояния (остановке и возобновлении). В этом случае используйте флаг
SA_NOCLDSTOP
и установите обработчик сигнала, вызывающий wait
(или родственную ей функцию) для получения данных процесса. В общем вы не можете ожидать получать по одному сигналу
SIGCHLD
на каждого завершающегося потомка. Следует считать, что SIGCHLD
означает «завершился по крайней мере один потомок» и быть готовым собрать при обработке SIGCHLD
сведения о как можно большем числе потомков. Следующая программа,
ch10-reap1.с
, блокирует SIGCHLD
до тех пор, пока не будет готова восстановить потомков. 1 /* ch10-reap1.с --- демонстрирует управление SIGCHLD с использованием цикла */
2
3 #include <stdio.h>
4 #include <errno.h>
5 #include <signal.h>
6 #include <string.h>
7 #include <sys/types.h>
8 #include <sys/wait.h>
9
10 #define MAX_KIDS 42
11 #define NOT_USED -1
12
13 pid_t kids[MAX_KIDS];
14 size_t nkids = 0;
Массив потомков отслеживает ID порожденных процессов. Если элемент содержит
NOT_USED
, он не представляет необработанного потомка. (Его инициализируют строки 89–90 внизу) nkids
указывает, сколько значений в kids
следует проверить. 16 /* format_num --- вспомогательная функция, поскольку нельзя использовать [sf]printf */
17
18 const char *format_num(int num)
19 {
20 #define NUMSIZ 30
21 static char buf[NUMSIZ];
22 int i;
23
24 if (num <= 0) {
25 strcpy(buf, "0");
26 return buf;
27 }
28
29 i = NUMSIZ - 1;
30 buf[i--] = '\0';
31
32 /* Преобразует цифры обратно в строку. */
33 do {
34 buf[i--] = (num % 10) + '0';
35 num /= 10;
36 } while (num > 0);
37
38 return &buf[i+1];
39 }
Поскольку обработчики сигналов не должны вызывать функции семейства
printf
, мы предусмотрели для преобразования десятичного сигнала или номера PID в строку простую «вспомогательную» функцию format_num
. Это примитивно, но работает. 41 /* childhandler --- перехват SIGCHLD, сбор сведений со всех доступных потомков */
42
43 void childhandler(int sig)
44 {
45 int status, ret;
46 int i;
47 char buf[100];
48 static const char entered[] = "Entered childhandler\n" ;
49 static const char exited[] = "Exited childhandler\n";
50
51 writed, entered, strlen(entered));
52 for (i =0; i < nkids; i++) {
53 if (kids[i] == NOT_USED)
54 continue;
55
56 retry:
57 if ((ret = waitpid(kids[i], &status, WNOHANG)) == kids[i]) {
58 strcpy(buf, "\treaped process ");
59 strcat(buf, format_num(ret));
60 strcat(buf, "\n");
61 write(1, buf, strlen(buf));