table of contents
SIGNAL(2) | Руководство программиста Linux | SIGNAL(2) |
ИМЯ¶
signal - работа с сигналами ANSI C
ОБЗОР¶
#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
ОПИСАНИЕ¶
Работа вызова signal() различается в различных версиях UNIX, и такая же ситуация исторически сложилась и в различных версиях Linux. Не используйте его: используйте вместо него sigaction(2). Смотрите абзац Переносимость далее.
Вызов signal() устанавливает обработчик сигнала с номером signum в соответствии с параметром handler, который может быть равен SIG_IGN, SIG_DFL или адресу функции пользователя ("обработчик сигнала").
Если сигнал signum доставляется процессу, то происходит следующее:
- *
- Если значение обработчика равно SIG_IGN, то сигнал игнорируется.
- *
- Если значение обработчика равно SIG_DFL, то выполняется стандартное действие, связанное с сигналом (см. signal(7)).
- *
- Если значение обработчика равно адресу функции, то сначала значение обработчика сбрасывается в SIG_DFL или сигнал блокируется (см. Переносимость далее), а затем вызывается функция handler с аргументом signum. Если вызов обработчика приводит к блокировке сигнала, то сигнал разблокируется после возврата из обработчика.
Сигналы SIGKILL и SIGSTOP не могут быть перехвачены или игнорированы.
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ¶
Вызов signal() возвращает предыдущее значение обработчика сигнала или SIG_ERR при ошибке.
ОШИБКИ¶
- EINVAL
- Неверное значение signum.
СООТВЕТСТВИЕ СТАНДАРТАМ¶
C89, C99, POSIX.1-2001.
ЗАМЕЧАНИЯ¶
Результат работы signal() в многонитиевом процессе не регламентирован.
В соответствии с POSIX поведение процесса после игнорирования сигнала SIGFPE, SIGILL или SIGSEGV не определено, если эти сигналы не были посланы при помощи функций kill(2) или raise(3). Деление целого числа на ноль имеет непредсказуемый результат. В некоторых архитектурах это приводит к появлению сигнала SIGFPE. (Также, деление самого большого по модулю отрицательного числа на -1 тоже может приводить к SIGFPE.) Игнорирование этого сигнала может привести к появлению бесконечного цикла.
О том, что происходит когда SIGCHLD устанавливается в SIG_IGN, смотрите на странице sigaction(2).
Список асинхронных функций работы с сигналами, которые можно безопасно вызывать из обработчика сигналов, смотрите на странице signal(7).
Используемый
sighandler_t
является
расширением
GNU, который
определён,
если
существует
макрос _GNU_SOURCE;
в glibc также
есть sig_t
(появился
из BSD), если
определён
_BSD_SOURCE. Без
использования
такого
типа
объявление
signal() сложнее
читать:
void ( *signal(int signum, void (*handler)(int)) ) (int);
Переносимость¶
Вызов signal() считается переносимым, если обработчик сигнала равен SIG_DFL или SIG_IGN. Семантика при использовании signal() для установки обработчика сигнала отличается в различных системах (и в POSIX.1 явно разрешена такая перемена); не используйте данный вызов для этой цели.
В POSIX.1 проблема переносимости решена введением sigaction(2), который предоставляет явное управление семантикой при вызове обработчика сигнала; используйте этот интерфейс вместо signal().
В первых системах UNIX, когда обработчик, установленный с помощью signal(), вызывался по получению сигнала, обработчик сигнала был бы сброшен в SIG_DFL, и система не заблокировала бы доставку этого сигнала в последующие экземпляры. System V также предоставляет эту семантику signal(). Это плохо, так как сигнал может быть доставлен снова, до того как обработчик сможет получить шанс его переустановить. Кроме того, скоростные доставки одного сигнала приводили к рекурсивным вызовам обработчика.
В BSD улучшили эту ситуацию изменив семантику обработки сигнала (но, к сожалению, по-тихому изменили семантику для установки обработчика с помощью signal()). В BSD при вызове обработчика сигнала обработчик сигнала не сбрасывается, и дальнейшие экземпляры сигнала блокируются и не доставляются пока выполняется обработчик.
Ситуация в Linux:
- Системный вызов ядра signal() предоставляет семантику System V.
- По
умолчанию
в glibc 2 и новее
обёрточная
функция signal()
не
вызывает
системный
вызов ядра.
Вместо
этого она
вызывает
sigaction(2) с
флагами,
которые
активируют
семантику
BSD. Такое
поведение
по
умолчанию
устанавливается,
если
определён
макрос
тестирования
свойств
_BSD_SOURCE. По
умолчанию
_BSD_SOURCE
определён;
также, он
неявно
определён,
если
определён
_GNU_SOURCE, и,
естественно,
может быть
определён
вручную.
В glibc 2 и более новых, если не установлен макрос тестирования свойств _BSD_SOURCE, то signal() предоставляет семантику System V. (По умолчанию неявное определение _BSD_SOURCE не происходит, если gcc(1) вызывается в одном из своих стандартных режимов (-std=xxx или -ansi) или определяются другие макросы тестирования свойств, такие как _POSIX_SOURCE, _XOPEN_SOURCE или _SVID_SOURCE; см. feature_test_macros(7).)
- Функция signal() в Linux libc4 и libc5 предоставляет семантику System V. Если в некоторую систему с libc5 включён <bsd/signal.h> вместо <signal.h>, то signal() предоставляет семантику BSD.
СМОТРИТЕ ТАКЖЕ¶
kill(1), alarm(2), kill(2), killpg(2), pause(2), sigaction(2), signalfd(2), sigpending(2), sigprocmask(2), sigsuspend(2), bsd_signal(3), raise(3), siginterrupt(3), sigqueue(3), sigsetops(3), sigvec(3), sysv_signal(3), signal(7)
2012-05-05 | Linux |