Linux программирование в примерах
Шрифт:
Которая из функций
act->sa_handler
и act->sa_sigaction
используется, зависит от флага SA_SIGINFO
в act->sa_flags
. Когда имеется, используется act->sa_sigaction
; в противном случае используется act->sa_handler
. Как POSIX, так и справочная страница GNU/Linux указывают, что эти два поля могут перекрываться в памяти (т. е. быть частью union
). Таким образом, никогда не следует использовать оба поля в одной и той же struct sigaction
. Поле
sa_flags
составляется с помощью побитового ИЛИ значений одного или более флагов, перечисленных в табл. 10.3. Таблица 10.3. Значения флагов для
sa_flags
Флаг | Значение |
---|---|
SA_NOCLDSTOP | Этот
SIGCHLD . Когда он установлен, родитель не получает сигнал при остановке порожденною процесса сигналами SIGSTOP , SIGTSTP , SIGTTIN или SIGTTOU . Эти сигналы обсуждаются позже, в разделе 10.8.2 |
SA_NOCLDWAIТ | Этот флаг имеет смысл лишь для SIGCHLD . Его поведение сложно. Мы отложим объяснение на потом, см. раздел 10.8.3 |
SA_NODEFER | Обычно данный сигнал блокируется, когда вызывается обработчик сигнала. Когда установлен один из этих флагов, данный сигнал не блокируется при запуске обработчика SA_NODEFER является официальным именем POSIX данного флага (которое и следует использовать) |
SA_NOMASK | Альтернативное имя для SA_NODEFER [110] |
SA_SIGINFO | Обработчик сигнала принимает три аргумента. Как упоминалось, при данном установленном флаге должно использоваться поле sa_sigaction вместо sa_handler . |
SA_ONSTACK | Это продвинутая возможность. Обработчики сигналов могут вызываться с использованием предоставленной пользователем памяти в качестве «альтернативного стека сигнала». Эта память даётся ядру для подобного использования посредством sigaltstack (см. sigaltstack(2)). Эта особенность больше не описывается в данной книге |
SA_RESETHAND | Этот флаг обеспечивает поведение V7: после вызова обработчика восстанавливается действие сигнала по умолчанию. Официальным именем POSIX флага (которое следует использовать) является SA_RESETHAND |
SA_ONESHOT | Альтернативное имя для SA_RESETHAND. |
SA_RESTART | Этот флаг предоставляет семантику BSD: системные вызовы, которые могут завершиться с ошибкой EINTR и которые получают этот сигнал, запускаются повторно. |
110
Насколько мы смогли определить, имена
SA_NOMASK
и SA_ONESHOT
являются специфическими для GNU/Linux. Если кому-нибудь известно иное, пожалуйста, сообщите нам! Когда в
act->sa_flags
установлен флаг SA_SIGINFO
, поле act->sa_sigaction
является указателем на функцию, объявленную следующим образом: void action_handler(int sig, siginfo_t *info, void *context) {
/* Здесь тело обработчика */
}
Структура
siginfo
_t предоставляет изобилие сведений о сигнале: /* Определение POSIX 2001. Действительное содержание может на разных системах быть разным. */
typedef struct {
int si_signo; /* номер сигнала */
int si_errno; /* значение <errno.h> при ошибке */
int si_code; /* код сигнала; см. текст */
pid_t si_pid; /* ID процесса, пославшего сигнал */
uid_t si_uid; /* настоящий UID посылающего процесса */
void *si_addr; /* адрес вызвавшей ошибку инструкции */
int si_status; /* значение завершения, может включать death-by-signal */
long si_band; /* связывающее событие для SIGPOLL/SIGIO */
union sigval si_value; /* значение сигнала (расширенное) */
} siginfo_t;
Поля
si_signo
, si_code
и si_value
доступны для всех сигналов. Другие поля могут быть членами объединения, поэтому должны использоваться лишь для тех сигналов, для которых они определены. В структуре siginfo_t
могут быть также и другие поля. Почти все поля предназначены для расширенного использования. Все подробности содержатся в стандарте POSIX и справочной странице sigaction(2). Однако, мы можем описать простое использование поля
si_code
. Для
SIGBUS
, SIGCHLD
, SIGFPE
, SIGILL
, SIGPOLL
, SIGSEGV
и SIGTRAP
поле si_code может принимать любое из набора предопределенных значений, специфичных для каждого сигнала, указывая на причину появления сигнала. Откровенно говоря, детали несколько чрезмерны; повседневному коду на самом деле нет необходимости иметь с ними дела (хотя позже мы рассмотрим значения для SIGCHLD
). Для всех остальных сигналов член si_code
имеет одно из значений из табл. 10.4. Таблица 10.4. Значения происхождения сигнала для
si_code
Значение | Только GLIBC | Смысл |
---|---|---|
SI_ASYNCIO | Асинхронный ввод/вывод завершен (расширенный). | |
SI_KERNEL | √ | Сигнал послан ядром. |
SI_MESGQ | Состояние очереди сообщений изменилось (расширенный.) | |
SI_QUEUE | Сигнал послан из sigqueue (расширенный). | |
SI_SIGIO | √ | SIGIO поставлен в очередь (расширенный). |
SI_TIMER | Время таймера истекло | |
SI_USER | Сигнал послан функцией kill . raise и abort также могут его вызвать, но это не обязательно. |
В особенности полезно значение
SI_USER
; оно позволяет обработчику сигнала сообщить, был ли сигнал послан функциями raise
или kill
(описываются далее). Вы можете использовать эту информацию, чтобы избежать повторного вызова raise
или kill
. Третий аргумент обработчика сигнала с тремя аргументами,
void *contex
t, является расширенной возможностью, которая больше не обсуждается в данной книге. Наконец, чтобы увидеть
sigaction
в действии, исследуйте полный исходный код обработчика сигнала для sort.c
: 2074 static void
2075 sighandler(int sig)
2076 {
2077 #ifndef SA_NOCLDSTOP /* В системе старого стиля... */
2078 signal(sig, SIG_IGN); /* - для игнорирования sig используйте signal*/
2079 #endif - /* В противном случае sig автоматически блокируется */
2080
2081 cleanup; /* Запуск кода очистки */
2082
2083 #ifdef SA_NOCLDSTOP /* В системе в стиле POSIX... */
2084 {
2085 struct sigaction sigact;
2086
2087 sigact.sa_handler = SIG_DFL; /* - Установить действие по умолчанию */
2088 sigemptyset(&sigact.sa_mask); /* - Нет дополнительных сигналов для блокирования */
2089 sigact.sa_flags = 0; /* - Специальные действия не предпринимаются */
2090 sigaction(sig, &sigact, NULL); /* - Поместить на место */
2091 }
2092 #else /* На системе в старом стиле... */
2093 signal(sig, SIG_DFL); /* - Установить действие по умолчанию */
2094 #endif
Поделиться с друзьями: