Linux программирование в примерах
Часть 152 из 253 Информация о книге
$ <b>ch10-reap2</b> /* Запустить программу */waiting for signalsEntered childhandler /* Опрос одного потомка */reaped process 2702pid 2703 not available yetpid 2704 not available yetpid 2705 not available yetpid 27 06 not available yetExited childhandlerwaiting for signalsEntered childhandler /* И следующего */reaped process 2703pid 2704 not available yetpid 2705 not available yetpid 2706 not available yetExited childhandlerwaiting for signalsEntered childhandler /* И так далее */reaped process 2704pid 2705 not available yetpid 2706 not available yetExited childhandlerwaiting for signalsEntered childhandlerreaped process 2705pid 2706 not available yetExited childhandlerwaiting for signalsEntered childhandlerreaped process 2706Exited childhandlerВ данном примере на каждый процесс поступает ровно один
! Хотя это прекрасно и полностью воспроизводимо на этой системе, это также необычно. Как на более раннем, так и на более позднем ядре и на Solaris программа получает один сигнал для более чем одного потомка:SIGCHLD$ <b>uname -a</b> /* Отобразить версию системы */Linux example2 2.4.22-1.2115.npt1 #1 Wed Oct 29 15:42:51 EST 2003 i686 i686 i386 GNU/Linux$ <b>ch10-reap2</b> /* Запуск программы */waiting for signalsEntered childhandler /* Обработчик сигнала вызван лишь однажды */reaped process 9564reaped process 9565reaped process 9566reaped process 9567reaped process 9568Exited childhandlerЗАМЕЧАНИЕ. В коде для
есть один важный дефект — состояние гонки. Взгляните еще раз на строки 106–112 вch10-reap2.c. Что случится, еслиch10-reap2.cпоявится при исполнении этого кода? МассивSIGCHLDи переменныеkidsиnkidsмогут оказаться разрушенными: код вkidsleftдобавляет новый процесс, но обработчик сигнала вычитает один.mainЭтот пример кода является отличным примером критического раздела; он не должен прерываться при исполнении. Правильным способом работы с этим кодом является заключение его между вызовами, которые сначала блокируют, а затем разблокируют
.SIGCHLD10.8.3.3. Строгий родительский контроль
Структура
и перехватчик сигнала с тремя аргументами дают возможность узнать, что случилось с потомком. Для SIGCHLD полеsiginfo_tструктурыsi_codeуказывает причину посылки сигнала (остановка, возобновление, завершение порожденного процесса и т.д.). В табл. 10.5 представлен полный список значений. Все они определены в качестве расширения XSI стандарта POSIX.siginfo_tСледующая программа,
, демонстрирует использование структурыch10-status.c.siginfo_t1 /* ch10-status.c --- демонстрирует управление SIGCHLD, используя обработчик с 3 аргументами */23 #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>910 void manage(siginfo_t *si);11/* ...не изменившийся для format_num() код опущен... */Таблица 10.5. Значения
XSI дляsi_codeSIGCHLD
Значение Смысл CLD_CONTINUEDОстановленный потомок был возобновлен. CLD_DUMPEDПотомок завершился с ошибкой, создан образ процесса CLD_EXITEDПотомок завершился нормально. CLD_KILLEDПотомок был завершен сигналом CLD_STOPPEDПорожденный процесс был остановлен. CLD_TRAPPEDТрассируемый потомок остановлен (Это условие возникает, когда программа трассируется — либо из отладчика, либо для мониторинга реального времени В любом случае, вы вряд ли увидите его в обычных ситуациях.) Строки 3–8 включают стандартные заголовочные файлы, строка 10 объявляет
, которая имеет дело с изменениями состояния потомка, а функцияmanage()не изменилась по сравнению с предыдущим.format_num()