| signal(2) | System Calls Manual | signal(2) |
signal - работа с сигналами ANSI C
Стандартная библиотека языка C (libc, -lc)
#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 доставляется процессу, то происходит следующее:
Сигналы SIGKILL и SIGSTOP не могут быть перехвачены или игнорированы.
Функция signal() возвращает предыдущее значение обработчика сигнала. В случае сбоя она возвращает SIG_ERR, и errno устанавливается, чтобы указать на ошибку.
Используемый sighandler_t является расширением GNU, который определён, если существует макрос _GNU_SOURCE; в glibc также есть sig_t, если определён _BSD_SOURCE (glibc 2.19 и старее) или _DEFAULT_SOURCE (glibc 2.19 и новее). Без использования этого типа объявление signal() сложнее читать:
void ( *signal(int signum, void (*handler)(int)) ) (int);
Вызов signal() считается переносимым, если обработчик сигнала равен SIG_DFL или SIG_IGN. Семантика при использовании signal() для установки обработчика сигнала отличается в различных системах (и в POSIX.1 явно разрешена такая перемена); не используйте данный вызов для этой цели.
В POSIX.1 проблема переносимости решена введением sigaction(2), который предоставляет явное управление семантикой при вызове обработчика сигнала; используйте этот интерфейс вместо signal().
C11, POSIX.1-2008.
C89, POSIX.1-2001.
В первых системах UNIX, когда обработчик, установленный с помощью signal(), вызывался по получению сигнала, обработчик сигнала был бы сброшен в SIG_DFL, и система не заблокировала бы доставку этого сигнала в последующие экземпляры.
sa.sa_flags = SA_RESETHAND | SA_NODEFER;
System V также предоставляет эту семантику signal(). Это плохо, так как сигнал может быть доставлен снова, до того как обработчик сможет получить шанс его переустановить. Кроме того, скоростные доставки одного сигнала приводили к рекурсивным вызовам обработчика.
В BSD улучшили эту ситуацию, но, к сожалению, изменили существующую семантику для установки обработчика с помощью signal(). В BSD при вызове обработчика сигнала обработчик сигнала не сбрасывается, и дальнейшие экземпляры сигнала блокируются и не доставляются пока выполняется обработчик. Кроме этого, некоторые блокирующие системные вызовы автоматически перезапускаются при прерывании обработчиком сигнала (смотрите signal(7)). Семантика BSD эквивалентна вызову sigaction(2) со следующими флагами:
sa.sa_flags = SA_RESTART;
Ситуация в Linux:
Результат работы signal() в многонитевом процессе не регламентирован.
В соответствии с POSIX поведение процесса после игнорирования сигнала SIGFPE, SIGILL или SIGSEGV не определено, если эти сигналы не были посланы при помощи функций kill(2) или raise(3). Деление целого числа на ноль имеет непредсказуемый результат. В некоторых архитектурах это приводит к появлению сигнала SIGFPE. (Также, деление самого большого по модулю отрицательного числа на -1 тоже может приводить к SIGFPE.) Игнорирование этого сигнала может привести к появлению бесконечного цикла.
О том, что происходит когда обработчик SIGCHLD приравнивается к SIG_IGN, смотрите на странице sigaction(2).
Список асинхронных функций работы с сигналами, которые можно безопасно вызывать из обработчика сигналов, смотрите на странице signal-safety(7).
kill(1), alarm(2), kill(2), pause(2), sigaction(2), signalfd(2), sigpending(2), sigprocmask(2), sigsuspend(2), bsd_signal(3), killpg(3), raise(3), siginterrupt(3), sigqueue(3), sigsetops(3), sigvec(3), sysv_signal(3), signal(7)
Русский перевод этой страницы руководства разработал(и) Alexander Golubev <fatzer2@gmail.com>, Azamat Hackimov <azamat.hackimov@gmail.com>, Hotellook, Nikita <zxcvbnm3230@mail.ru>, Spiros Georgaras <sng@hellug.gr>, Vladislav <ivladislavefimov@gmail.com>, Yuri Kozlov <yuray@komyakino.ru>, Иван Павлов <pavia00@gmail.com> и Kirill Rekhov <krekhov.dev@gmail.com>
Этот перевод является свободной программной документацией; он распространяется на условиях общедоступной лицензии GNU (GNU General Public License - GPL, https://www.gnu.org/licenses/gpl-3.0.html версии 3 или более поздней) в отношении авторского права, но БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ.
Если вы обнаружите какие-либо ошибки в переводе этой страницы руководства, пожалуйста, сообщите об этом разработчику(ам) по его(их) адресу(ам) электронной почты или по адресу списка рассылки русских переводчиков.
| 2 мая 2024 г. | Справочные страницы Linux 6.9.1 |