waiting for signals

Entered childhandler /* Обработчик сигнала вызван лишь однажды */

  reaped process 9564

  reaped process 9565

  reaped process 9566

  reaped process 9567

  reaped process 9568

Exited childhandler

ЗАМЕЧАНИЕ. В коде для ch10-reap2.c есть один важный дефект — состояние гонки. Взгляните еще раз на строки 106–112 в ch10-reap2.c. Что случится, если SIGCHLD появится при исполнении этого кода? Массив kids и переменные nkids и kidsleft могут оказаться разрушенными: код в main добавляет новый процесс, но обработчик сигнала вычитает один.

Этот пример кода является отличным примером критического раздела; он не должен прерываться при исполнении. Правильным способом работы с этим кодом является заключение его между вызовами, которые сначала блокируют, а затем разблокируют SIGCHLD.

<p>10.8.3.3. Строгий родительский контроль</p>

Структура siginfo_t и перехватчик сигнала с тремя аргументами дают возможность узнать, что случилось с потомком. Для SIGCHLD поле si_code структуры siginfo_t указывает причину посылки сигнала (остановка, возобновление, завершение порожденного процесса и т.д.). В табл. 10.5 представлен полный список значений. Все они определены в качестве расширения XSI стандарта POSIX.

Следующая программа, ch10-status.c, демонстрирует использование структуры siginfo_t.

1  /* ch10-status.c --- демонстрирует управление SIGCHLD, используя обработчик с 3 аргументами */

2

3  #include

4  #include

5  #include

6  #include

7  #include

8  #include

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));

Перейти на страницу:

Похожие книги