7
POSIX позволяет нам задавать набор сигналов, которые будут sa_mask
равным пустому набору. Это означает, что во время работы обработчика дополнительные сигналы не блокируются. POSIX гарантирует, что перехватываемый сигнал всегда блокирован, пока выполняется его обработчик.
8-17
Флаг SA_RESTART
не является обязательным, и если он установлен, то системный вызов, прерываемый этим сигналом, будет автоматически снова выполнен ядром. (В продолжении нашего примера мы более подробно поговорим о прерванных системных вызовах.) Если перехватываемый сигнал не является сигналом SIGALRM
, мы задаем флаг SA_RESTART
, если таковой определен. (Причина, по которой сигнал SIGALRM
обрабатывается отдельно, состоит в том, что обычно цель его генерации - ввести ограничение по времени в операцию ввода-вывода, как показано в листинге 14.2. В этом случае мы хотим, чтобы блокированный системный вызов был прерван сигналом.) Более ранние системы, особенно SunOS 4.x, автоматически перезапускают прерванный системный вызов по умолчанию и затем определяют флаг SA_INTERRUPT
. Если этот флаг задан, мы устанавливаем его при перехвате сигнала SIGALRM
.
18-20
Мы вызываем функцию sigaction
, а затем возвращаем старое действие сигнала как результат функции signal
.
В книге мы везде используем функцию signal
из листинга 5.5.
Семантика сигналов POSIX
Сведем воедино следующие моменты, относящиеся к обработке сигналов в системе, совместимой с POSIX.
■ Однажды установленный обработчик сигналов остается установленным (в более ранних системах обработчик сигналов удалялся каждый раз по выполнении).
■ На время выполнения функции — обработчика сигнала доставляемый сигнал блокируется. Более того, любые дополнительные сигналы, заданные в наборе сигналов sa_mask
, переданном функции sigaction
при установке обработчика, также блокируются. В листинге 5.5 мы устанавливаем sa_mask
равным пустому набору, что означает, что никакие сигналы, кроме перехватываемого, не блокируются.
■ Если сигнал генерируется один или несколько раз, пока он блокирован, то обычно после разблокирования он доставляется только один раз, то есть по умолчанию сигналы Unix не
■ Существует возможность выборочного блокирования и разблокирования набора сигналов с помощью функции sigprocmask
. Это позволяет нам защитить критическую область кода, не допуская перехватывания определенных сигналов во время ее выполнения.
5.9. Обработка сигнала SIGCHLD
Назначение состояния зомби — сохранить информацию о дочернем процессе, чтобы родительский процесс мог ее впоследствии получить. Эта информация включает идентификатор дочернего процесса, статус завершения и данные об использовании ресурсов (время процессора, память и т.д.). Если у завершающегося процесса есть дочерний процесс в зомбированном состоянии, идентификатору родительского процесса всех зомбированных дочерних процессов присваивается значение 1 (процесс init
), что позволяет унаследовать дочерние процессы и сбросить их (то есть процесс init
будет ждать (wait
) их завершения, благодаря чему будут удалены зомби). Некоторые системы Unix в столбце COMMAND
выводят для зомбированных процессов значение
.
Обработка зомбированных процессов
Очевидно, что нам не хотелось бы оставлять процессы в виде зомби. Они занимают место в ядре, и в конце концов у нас может не остаться идентификаторов для нормальных процессов. Когда мы выполняем функцию fork
для дочерних процессов, необходимо с помощью функции wait
дождаться их завершения, чтобы они не превратились в зомби. Для этого мы устанавливаем обработчик сигналов для перехватывания сигнала SIGCHLD
и внутри обработчика вызываем функцию wait
. (Функции wait
и waitpid
мы опишем в разделе 5.10.) Обработчик сигналов мы устанавливаем с помощью вызова функции
Signal(SIGCHLD, sig_chld);
в листинге 5.1, после вызова функции listen
. (Необходимо сделать это до вызова функции fork
для первого дочернего процесса, причем только один раз.) Затем мы определяем обработчик сигнала — функцию sig_chld
, представленную в листинге 5.6.
Листинг 5.6. Версия обработчика сигнала SIGCHLD, вызывающая функцию wait (усовершенствованная версия находится в листинге 5.8)
//tcpcliserv/sigchldwait.с
1 #include "unp.h"
2 void
3 sig_chld(int signo)
4 {
5 pid_t pid;
6 int stat;