Linux программирование в примерах
117 }118119 return 0;120 }Программа
все устанавливает. Строки 100–103 помещают на место обработчик. Строка 100 устанавливает флагmain()таким образом, что используется обработчик с тремя аргументами. Строки 105–108 блокируютSA_SIGINFO.SIGCHLDСтрока 110 создает порожденный процесс. Строки 113–117 продолжаются в родителе, используя для ожидания входящих сигналов
.sigsuspend()123 /* manage --- разрешение различных событий, которые могут случиться с потомком */124125 void manage(siginfo_t *si)126 {127 char buf[100];128129 switch (si->si_code) {130 case CLD_STOPPED:131 write(1, "\tchild stopped, restarting\n", 27);132 kill(si->si_pid, SIGCONT);133 break;134135 case CLD_CONTINUED: /* not sent on Linux */136 write(1, "\tchild continued\n", 17);137 break;138139 case CLD_EXITED:140 strcpy(buf, "\tchild exited with status ");141 strcat(buf, format_num(si->si_status));142 strcat(buf, "\n");143 write(1, buf, strlen(buf));144 exit(0); /* we're done */145 break;146147 case CLD_DUMPED:148 write(1, "\tchild dumped\n", 14);149 break;150151 case CLD_KILLED:152 write(1, " \tchild killed\n", 14);153 break;154155 case CLD_TRAPPED:156 write(1, "\tchild trapped\n", 15);157 break;158 }159 }Посредством функции
родитель обрабатывает изменение состояния в порожденном процессе,manage()вызывается, когда изменяется состояние и когда порожденный процесс завершился.manage()Строки 130–133 обрабатывают случай, когда потомок остановился; родитель возобновляет его, посылая
.SIGCONTСтроки 135–137 выводят уведомление о возобновлении потомка. Это событие на системах GNU/Linux не происходит, и стандарт POSIX использует в этом случае невыразительный язык, просто говоря, что это событие может появиться, а не появится.
Строки 139–145 обрабатывают случай, когда порожденный процесс завершается, выводя статус завершения. Для этой программы родитель также все сделал, поэтому код завершается, хотя в более крупной программе это не то действие, которое должно быть сделано.
Другие случаи более специализированные. В случае события
для получения дополнительных сведений было бы полезным значениеCLD_KILLED, заполненной функциейstatus.waitpid()Вот что происходит при запуске:
$ <b>ch10-status</b> /* Запуск программы */waiting for signalsEntered childhandler /* Вход в обработчик сигнала */pid 24279 changed statuschild stopped, restarting /* Обработчик действует */Exited childhandlerwaiting for signals---> child restarted <--- /* Из потомка */Entered childhandlerreaped process 24279 /* Обработчик родителя опрашивает потомка */child exited with status 42К сожалению, поскольку нет способа гарантировать доставку по одному
на каждый процесс, ваша программа должна быть готова восстановить несколько потомков за один проход.SIGCHLD10.9. Сигналы, передающиеся через
иfork()exec()Когда программа вызывает
, ситуация с сигналами в порожденном процессе почти идентична ситуации в родительском процессе. Установленные обработчики остаются на месте, заблокированные сигналы остаются заблокированными и т.д. Однако, любые ожидающие в родителе сигналы в потомке сбрасываются, включая установленный с помощьюfork()временной интервал. Это просто, и это имеет смысл.alarm()Когда процесс вызывает одну из функций
, положение в новой программе следующее:exec()• Сигналы с установленным действием по умолчанию остаются с этим действием по умолчанию.
• Все перехваченные сигналы сбрасываются в состояние с действием по умолчанию.
• Сигналы, которые игнорируются, продолжают игнорироваться. Особым случаем является
. ЕслиSIGCHLDдо вызоваSIGCHLDигнорировался, он может игнорироваться также и после вызова. В качестве альтернативы для него может быть восстановлено действие по умолчанию. То, что происходит на самом деле, стандартом POSIX намеренно не определяется. (Справочные страницы GNU/Linux не определяют, что делает Linux, и поскольку POSIX оставляет это не определенным, любой код, который вы пишете для использованияexec(), должен быть подготовлен для обработки любого случая.)SIGCHLD• Сигналы, заблокированные до вызова
, остаются заблокированными и после вызова. Другими словами, новая программа наследует маску сигналов существующего процесса.exec()• Любые ожидающие сигналы (те, которые появились, но были заблокированы) сбрасываются. Новая программа не может их получить.