Linux программирование в примерах
Шрифт:
1 /* ch10-status.c --- демонстрирует управление SIGCHLD, используя обработчик с 3 аргументами */
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 void manage(siginfo_t *si);
11
/* ...не изменившийся для format_num
код опущен... */
Таблица 10.5. Значения
si_code
XSI для SIGCHLD
| Значение | Смысл |
|---|---|
CLD_CONTINUED | Остановленный потомок был возобновлен. |
CLD_DUMPED | Потомок завершился с ошибкой, создан образ процесса |
CLD_EXITED | Потомок завершился нормально. |
CLD_KILLED | Потомок был завершен сигналом |
CLD_STOPPED | Порожденный процесс был остановлен. |
CLD_TRAPPED | Трассируемый потомок остановлен (Это условие возникает, когда программа трассируется — либо из отладчика, либо для мониторинга реального времени В любом случае, вы вряд ли увидите его в обычных ситуациях.) |
Строки 3–8 включают стандартные заголовочные файлы, строка 10 объявляет
manage
, которая имеет дело с изменениями состояния потомка, а функция format_num
не изменилась по сравнению с предыдущим. 37 /* childhandler --- перехват SIGCHLD, сбор данных лишь об одном потомке */
38
39 void childhandler(int sig, siginfo_t *si, void *context)
40 {
41 int status, ret;
42 int i;
43 char buf[100];
44 static const char entered[] = "Entered childhandler\n";
45 static const char exited[] = "Exited childhandler\n";
46
47 write(1, entered, strlen(entered));
48 retry:
49 if ((ret = waitpid(si->si_pid, &status, WNOHANG)) == si->si_pid) {
50 strcpy(buf, "\treaped process ");
51 strcat(buf, format_num(si->si_pid));
52 strcat(buf, "\n");
53 write(1, buf, strlen(buf));
54 manage(si); /* обработать то, что произошло */
55 } else if (ret > 0) {
56 strcpy(buf, "\treaped unexpected pid ");
57 strcat(buf, format_num(ret));
58 strcat(buf, "\n");
59 write(1, buf, strlen(buf));
60 goto retry; /* почему бы нет? */
61 } else if (ret == 0) {
62 strcpy(buf, "\tpid ");
63 strcat(buf, format_num(si->si_pid));
64 strcat(buf, " changed status\n");
65 write(1, buf, strlen(buf));
66 manage(si); /*
обработать то, что произошло */
67 } else if (ret == -1 && errno == EINTR) {
68 write(1, "\tretrying\n", 10);
69 goto retry;
70 } else {
71 strcpy(buf, "\twaitpid failed: ");
72 strcat(buf, strerror(errno));
73 strcat(buf, "\n");
74 write(1, buf, strlen(buf));
75 }
76
77 write(1, exited, strlen(exited));
78 }
Обработчик сигнала похож на показанные ранее. Обратите внимание на список аргументов (строка 39) и на то, что нет цикла.
Строки 49–54 обрабатывают завершение процесса, включая вызов
manage
для вывода состояния. Строки 55–60 обрабатывают случай неожиданного завершения потомка. Этого не должно происходить, поскольку обработчику сигнала передается специфическая для определенного порожденного процесса информация.
Строки 61–66 представляют для нас интерес: возвращаемое значение для изменений состояния равно 0.
manage
имеет дело с деталями (строка 66). Строки 67–69 обрабатывают прерывания, а строки 70–75 распоряжаются ошибками
80 /* child --- что сделать в порожденном процессе */
81
82 void child(void)
83 {
84 raise(SIGCONT); /* должен быть проигнорирован */
85 raise(SIGSTOP); /* заснуть, родитель снова разбудит */
86 printf("\t---> child restarted <---\n");
87 exit(42); /* нормальное завершение, дать возможность родителю получить значение */
88 }
Функция
child
обрабатывает поведение порожденного процесса, предпринимая действия для уведомления родителя [113] . Строка 84 посылает SIGCONT
, что может вызвать получение родителем события CLD_CONTINUED
. Строка 85 посылает SIGSTOP
, который останавливает процесс (сигнал не может быть перехвачен) и вызывает для родителя событие CLD_STOPPED
. Когда родитель возобновляет порожденный процесс, последний выводит сообщение, что он снова активен, а затем завершается с известным статусом завершения.113
Возможно, лучшим именем для функции было бы
child_at_school
[ребенок_в_школе] — Примеч. автора. 90 /* main --- установка относящихся к порожденному процессу сведений
и сигналов, создание порожденного процесса */
91
92 int main(int argc, char **argv)
93 {
94 pid_t kid;
95 struct sigaction sa;
96 sigset_t childset, emptyset;
97
98 sigemptyset(&emptyset);
99
Поделиться:
Популярные книги
Старый, но крепкий 3
3. Культивация без насилия
Фантастика:
рпг
уся
фэнтези
5.00
рейтинг книги
Эмиссар
8. Ушедший Род
Фантастика:
боевая фантастика
аниме
попаданцы
7.50
рейтинг книги
Газлайтер. Том 28
28. История Телепата
Фантастика:
боевая фантастика
аниме
попаданцы
5.00
рейтинг книги
Сопротивление
11. Последняя жизнь
Фантастика:
аниме
фэнтези
попаданцы
7.33
рейтинг книги
Кодекс Охотника. Книга VII
7. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
4.75
рейтинг книги
Чиновникъ Особых поручений
6. Александр Агренев
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Сталин
3. Загадки жизни и смерти
Проза:
историческая проза
7.36
рейтинг книги
Ваше Сиятельство
1. Ваше Сиятельство
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Идеальный мир для Лекаря 2
2. Лекарь
Фантастика:
юмористическая фантастика
попаданцы
аниме
5.00
рейтинг книги
На границе империй. Том 7
7. Фортуна дама переменчивая
Фантастика:
боевая фантастика
космическая фантастика
попаданцы
6.75
рейтинг книги
Изменяющий-Механик. Компиляция. Книги 1-18
Собрание сочинений
Фантастика:
боевая фантастика
космическая фантастика
5.00
рейтинг книги
Я до сих пор князь. Книга XXII
22. Дорогой барон!
Фантастика:
юмористическое фэнтези
аниме
попаданцы
5.00
рейтинг книги
Чужое наследие
3. Другая сторона
Фантастика:
боевая фантастика
8.47
рейтинг книги
Дважды одаренный. Том VIII
8. Дважды одаренный
Фантастика:
боевая фантастика
альтернативная история
аниме
попаданцы
5.00