Книга: Основы программирования в Linux
Множества сигналов
Разделы на этой странице:
Множества сигналов
В заголовочном файле signal.h определены тип sigset_t
и функции, применяемые для манипулирования множествами сигналов. Эти множества используются в sigaction
и других функциях для изменения поведения процесса при получении сигналов.
#include <signal.h>
int sigaddset(sigset_t *set, int signo);
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigdelset(sigset_t *set, int signo);
Приведенные функции выполняют операции, соответствующие их названиям, sigemptyset
инициализирует пустое множество сигналов. Функция sigfillset
инициализирует множество сигналов, заполняя его всеми заданными сигналами, sigaddset
и sigdelset
добавляют заданный сигнал (signo
) в множество сигналов и удаляют его из множества. Они все возвращают 0 в случае успешного завершения и -1 в случае ошибки, заданной в переменной errno
. Единственная определенная ошибка EINVAL
описывает сигнал как некорректный.
Функция sigismember
определяет, включен ли заданный сигнал в множество сигналов. Она возвращает 1, если сигнал является элементом множества, 0, если нет и -1 с errno
, равной EINVAL
, если сигнал неверный.
#include <signal.h>
int sigismember(sigset_t *set, int signo);
Маска сигналов процесса задается и просматривается с помощью функции sigprocmask
. Маска сигналов — это множество сигналов, которые заблокированы в данный момент и не будут приниматься текущим процессом.
#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oset);
Функция sigprocmask
может изменять маску сигналов процесса разными способами в соответствии с аргументом how
. Новые значения маски сигналов передаются в аргументе set
, если он не равен null
, а предыдущая маска сигналов будет записана в множество сигналов oset
.
Аргумент how
может принимать одно из следующих значений:
? SIG_BLOCK
— сигналы аргумента set
добавляются к маске сигналов;
? SIG_SETMASK
—маска сигналов задается аргументом set
;
? SIG_UNBLOCK
— сигналы в аргументе set
удаляются из маски сигналов.
Если аргумент set
равен null
, значение how
не используется и единственная цель вызова — перенести значение текущей маски сигналов в аргумент oset
.
Если функция sigprocmask
завершается успешно, она возвращает 0. Функция вернет -1, если параметр how
неверен, в этом случае переменная errno
будет равна EINVAL
.
Если сигнал заблокирован процессом, он не будет доставлен, но останется ждать обработки. Программа может определить с помощью функции sigpending
, какие из заблокированных ею сигналов ждут обработки.
#include <signal.h>
int sigpending(sigset_t *set);
Она записывает множество сигналов, заблокированных от доставки и ждущих обработки, в множество сигналов, на которое указывает аргумент set
. Функция возвращает 0 при успешном завершении и -1 в противном случае с переменной errno
, содержащей ошибку. Данная функция может пригодиться, когда программе потребуется обрабатывать сигналы и управлять моментом вызова функции обработки.
С помощью функции sigsuspend
процесс может приостановить выполнение, пока не будет доставлен один сигнал из множества сигналов. Это более общая форма функции pause
, с которой вы уже встречались.
#include <signal.h>
int sigsuspend(const sigset_t *sigmask);
Функция sigsuspend
замещает маску сигналов процесса множеством сигналов, заданным в аргументе sigmask
, и затем приостанавливает выполнение. Оно будет возобновлено после выполнения функции обработки сигнала. Если полученный сигнал завершает программу, sigsuspend
никогда не вернет ей управление. Если полученный сигнал не завершает программу, sigsuspend
вернет с переменной errno
, равной EINTR
.
Флаги sigaction
Поле sa_flags
структуры sigaction
, применяемой в функции sigaction
, может содержать значения, изменяющие поведение сигнала (табл. 11.5).
Таблица 11.5
Имя сигнала | Описание |
---|---|
SA_NOCLDSTOP |
Не генерируется SIGCHLD , когда дочерние процессы остановлены |
SA_RESETHAND |
Восстанавливает при получении действие, соответствующее значению SIG_DFL |
SA_RESTART |
Перезапускает прерванные функции вместо ошибки EINTR |
SA_NODEFER |
При перехвате сигнала не добавляет его а маску сигналов |
Флаг SA_RESETHAND
может применяться для автоматической очистки функции сигнала при захвате сигнала, как мы видели раньше.
Многие системные вызовы, которые использует программа, прерываемые, т.е. при получении сигнала они вернутся с ошибкой и переменная errno
получит значение EINTR
, чтобы указать, что функция вернула управление в результате получения сигнала. Поведение требует повышенного внимания со стороны приложения, использующего сигналы. Если в поле sa_flags
функции sigaction
установлен флаг SA_RESTART
, функция, которая в противном случае могла быть прервана сигналом, вместо этого будет возобновлена, как только выполнится функция обработки сигнала.
Обычно, когда функция обработки сигнала выполняется, полученный сигнал добавляется в маску сигналов процесса во время работы функции обработки. Это препятствует последующему появлению того же сигнала, заставляющему функцию обработки сигнала выполняться снова. Если функция не реентерабельная, вызов ее другим экземпляром сигнала до того, как она завершит обработку первого сигнала, может создать проблемы. Но если установлен флаг SA_NODEFER
, маска сигнала не меняется при получении этого сигнала.
Функция обработки сигнала может быть прервана в середине и вызвана снова чем-нибудь еще. Когда вы возвращаетесь к первому вызову функции, крайне важно, чтобы она все еще действовала корректно. Она должна быть не просто рекурсивной (вызывающей саму себя), а реентерабельной (в нее можно войти и выполнить ее снова). Подпрограммы ядра, обслуживающие прерывания и имеющие дело с несколькими устройствами одновременно, должны быть реентерабельными, поскольку высокоприоритетное прерывание может "войти" в тот код, который выполняется.
Функции, которые безопасно вызываются в обработчике сигнала и в стандарте X/Open гарантированно описанные либо как реентерабельные, либо как самостоятельно не возбуждающие сигналов, перечислены в табл. 11.6.
Все функции, не включенные в табл. 11.6, следует считать небезопасными в том, что касается сигналов.
Таблица 11.6
access |
alarm |
cfgetispeed |
cfgetospeed |
cfsetispeed |
cfsetospeed |
chdir |
chmod |
chown |
close |
creat |
dup2 |
dup |
execle |
execve |
exit |
fcntl |
fork |
fstat |
getegid |
geteuid |
getgid |
getgroups |
getpgrp |
getpid |
getppid |
getuid |
kill |
link |
lseek |
mkdir |
mkfifo |
open |
pathconf |
pause |
pipe |
read |
rename |
rmdir |
setgid |
setpgid |
setsid |
setuid |
sigaction |
sigaddset |
sigdelset |
sigemptyset |
sigfillset |
sigismember |
signal |
sigpending |
sigprocmask |
sigsuspend |
sleep |
stat |
sysconf |
tcdrain |
tcflow |
tcflush |
tcgetattr |
tcgetpgrp |
tcsendbreak |
tcsetattr |
tcsetpgrp |
time |
times |
umask |
uname |
unlink |
utime |
wait |
waitpid |
write |
Общая сводка сигналов
В этом разделе мы перечисляем сигналы, в которых нуждаются программы Linux и UNIX для обеспечения стандартных реакций.
Стандартное действие для сигналов, перечисленных в табл. 11.7, — аварийное завершение процесса со всеми последствиями вызова функции _exit
(которая похожа на exit
, но не выполняет никакой очистки перед возвратом управления ядру). Тем не менее, состояние становится доступным функции wait
, а функция waitpid
указывает на аварийное завершение, вызванное описанным сигналом.
Таблица 11.7
Имя сигнала | Описание |
---|---|
SIGALRM |
Генерируется таймером, установленным функцией alarm |
SIGHUP |
Посылается управляющему процессу отключающимся терминалом или управляющим процессом во время завершения каждому процессу с высоким приоритетом |
SIGINT |
Обычно возбуждается с терминала при нажатии комбинации клавиш <Ctrl>+<C> или сконфигурированного символа прерывания |
SIGKILL |
Обычно используется из командной оболочки для принудительного завершения процесса с ошибкой, т.к. этот сигнал не может быть перехвачен или проигнорирован |
SIGPIPE |
Генерируется при попытке записи в канал при отсутствии связанного с ним считывателя |
SIGTERM |
Отправляется процессу как требование завершиться. Применяется UNIX при выключении для запроса остановки системных сервисов. Это сигнал, по умолчанию посылаемый командой kill |
SIGUSR1 , SIGUSR2 |
Может использоваться процессами для взаимодействия друг с другом, возможно, чтобы заставить их сообщить информацию о состоянии |
По умолчанию сигналы, перечисленные в табл. 11.8, также вызывают преждевременное завершение. Кроме того, могут выполняться действия, зависящие от реализации, например, создание файла core.
Таблица 11.8
Имя сигнала | Описание |
---|---|
SIGFPE |
Генерируется исключительной ситуацией во время операций с плавающей точкой |
SIGILL |
Процессор выполнил недопустимую команду. Обычно возбуждается испорченной программой или некорректным модулем совместно используемой памяти |
SIGQUIT |
Обычно возбуждается с терминала при нажатии комбинации клавиш <Ctrl>+<> или сконфигурированного символа завершения (quit) |
SIGSEGV |
Нарушение сегментации, обычно возбуждается при чтении из некорректного участка памяти или записи в него, а также выход за границы массива или разыменование неверного указателя. Перезапись локального массива и повреждение стека могут вызвать сигнал SIGSEGV при возврате функции по неверному адресу |
При получении одного из сигналов, приведенных в табл. 11.9, по умолчанию процесс приостанавливается.
Таблица 11.9
Имя сигнала | Описание |
---|---|
SIGSTOP |
Останавливает выполнение (не может быть захвачен или проигнорирован) |
SIGTSTP |
Сигнал останова терминала часто возбуждается нажатием комбинации клавиш <Ctrl>+<Z> |
SIGTTIN , SIGTTOU |
Применяются командной оболочкой для обозначения того, что фоновые задания остановлены, т.к. им необходимо прочесть данные с терминала или выполнить вывод |
Сигнал SIGCONT
возобновляет остановленный процесс и игнорируется при получении неостановленным процессом. Сигнал SIGCHLD
по умолчанию игнорируется (табл. 11.10).
Таблица 11.10
Имя сигнала | Описание |
---|---|
SIGCONT |
Продолжает выполнение, если процесс остановлен |
SIGCHLD |
Возбуждается, когда останавливается или завершается дочерний процесс |
- Множества повышенной надежности
- Операции с множествами узлов
- 7.4. Аналоговые перемножители сигналов
- 15.1.3. Обработка сигналов управления заданиями
- Пример: обработчик управляющих сигналов консоли
- 10.6.4. Перехват сигналов: sigaction()
- 19.7.9. Обработка сигналов и протоколирование
- 10.6.3. Управление маской сигналов: sigprocmask() и др.
- Использование возможностей множества транзакций
- 10.2. Действия сигналов
- 10.3.2. Программная отправка сигналов: raise()
- 10.4. Обработчики сигналов в действии