| SIGNAL(7) | Руководство программиста Linux | SIGNAL(7) |
signal - обзор сигналов
В Linux поддерживаются надёжные (reliable) сигналы POSIX (далее, «стандартные сигналы») и сигналы реального времени POSIX.
Каждый сигнал имеет текущий обработчик, который определяет, что будет делать процесс при поступлении сигнала.
В таблице далее есть столбец «Действие», в котором указан обработчик по умолчанию для каждого сигнала:
Процесс может изменить обработчик сигнала с помощью sigaction(2) или signal(2) (менее переносим; дополнительную информацию смотрите в signal(2)). Используя данные системные вызовы процесс может выбрать одно из следующих действий при получении сигнала: выполнить действие по умолчанию, игнорировать сигнал, поймать сигнал обработчиком сигнала — функцией, задаваемой программистом, которая автоматически вызывается при получении сигнала (по умолчанию обработчик сигнала использует обычный стек процесса. Возможно сделать так, чтобы обработчик сигнала использовал альтернативный стек; как это делается и когда это может быть полезно смотрите в sigaltstack(2)).
Реакция на сигналы является атрибутом процесса: в многонитевом приложении реакция на определённый сигнал одинакова для всех нитей.
Потомок, созданный с помощью fork(2), наследует реакцию на сигналы от своего родителя. При execve(2) реакция на сигналы устанавливается в значение по умолчанию; реакция на игнорируемые сигналы не изменяется.
Для отправки сигнала можно использовать следующие системные вызовы и библиотечные функции:
Следующие системные вызовы приостанавливают выполнение вызывающей нити до тех пор, пока не будет пойман сигнал (или необработанный сигнал не завершит процесс):
В отличие от асинхронного получения сигнала через обработчик, возможно синхронно получить сигнал, то есть блокировать выполнение до поступления сигнала в некоторой точке, в которой ядро вернёт информацию о сигнале вызывающему. Для этого существует два пути:
Сигнал может быть заблокирован. Это означает, что он не будет доставлен до тех пор, пока не будет разблокирован. В промежуток времени от генерации сигнала и до его доставки о сигнале говорят как об ожидающем.
В каждой нити процесса имеется независимая сигнальная маска, определяющая набор сигналов, которые нить, в данный момент, блокирует. Нить может управлять сигнальной маской с помощью pthread_sigmask(3). В обычном однонитевом приложении для работы с сигнальной маской можно использовать вызов sigprocmask(2).
Потомок, создаваемый с помощью fork(2), наследует копию родительской маски сигналов; маска сигналов сохраняется при вызове execve(2).
Сигнал может быть сгенерирован (а значит и стать ожидающим) как для всего процесса (например, при отправке с помощью kill(2)) так и для отдельной нити (например, некоторые сигналы, такие как SIGSEGV и SIGFPE, сгенерированные в следствии выполнения определённой инструкции на машинном языке в самой нити, или сигналы, направленные определённой нити с помощью pthread_kill(3)). Направленный процессу сигнал может быть доставлен в любую из нитей, у которых сигнал не заблокирован. Если имеется несколько таких нитей, то ядро выбирает произвольную нить, которой и доставит сигнал.
Нить может получить набор сигналов, которые находятся в состоянии ожидания с помощью вызова sigpending(2). Этот набор будет состоять из объединения набора ожидающих сигналов, направленных процессу, и набора ожидающих сигналов для вызвавшей нити.
Потомок, созданный с помощью fork(2), первоначально имеет пустой набор ожидающих сигналов; набор ожидающих сигналов сохраняется при вызове execve(2).
Linux поддерживает стандартные сигналы, перечисленные далее. Во второй колонке таблицы указан стандарт (если есть), которым введён сигнал, например, «P1990» — сигнал описан в первоначальной версии стандарта POSIX.1-1990; «P2001» — сигнал добавлен в SUSv2 и POSIX.1-2001.
| Сигнал | Стандарт | Действие | Комментарий |
| SIGABRT | P1990 | Core | Сигнал аварии (abort), посланный abort(3) |
| SIGALRM | P1990 | Term | Сигнал таймера, посланный alarm(2) |
| SIGBUS | P2001 | Core | Ошибка шины (некорректный адрес доступа) |
| SIGCHLD | P1990 | Ign | Потомок остановлен или завершился |
| SIGCLD | - | Ign | Синоним SIGCHLD |
| SIGCONT | P1990 | Cont | Продолжить, если остановлен |
| SIGEMT | - | Term | Ловушка эмулятора |
| SIGFPE | P1990 | Core | Ошибка операций с плавающей запятой |
| SIGHUP | P1990 | Term | Обнаружен обрыв связи с управляющим |
| терминалом, либо завершение управляющего терминалом процесса | |||
| SIGILL | P1990 | Core | Недопустимая инструкция |
| SIGINFO | - | Синоним SIGPWR | |
| SIGINT | P1990 | Term | Прерывание с клавиатуры |
| SIGIO | - | Term | Теперь возможен ввод/вывод (4.2BSD) |
| SIGIOT | - | Core | Ловушка IOT. Синоним SIGABRT |
| SIGKILL | P1990 | Term | Kill-сигнал |
| SIGLOST | - | Term | Утрачена блокировка файла (не используется) |
| SIGPIPE | P1990 | Term | Обрыв канала: запись в канал без |
| читателей; смотрите pipe(7) | |||
| SIGPOLL | P2001 | Term | Опрашиваемое событие (Sys V) |
| Синоним SIGIO | |||
| SIGPROF | P2001 | Term | Время профилирования истекло |
| SIGPWR | - | Term | Отказ питания (System V) |
| SIGQUIT | P1990 | Core | Выход с клавиатуры |
| SIGSEGV | P1990 | Core | Некорректная ссылка в память |
| SIGSTKFLT | - | Term | Ошибка стека на сопроцессоре (не используется) |
| SIGSTOP | P1990 | Stop | Остановить процесс |
| SIGTSTP | P1990 | Stop | Останов введён с терминала |
| SIGSYS | P2001 | Core | Неправильный системный вызов (SVr4); |
| смотрите также seccomp(2) | |||
| SIGTERM | P1990 | Term | Сигнал завершения |
| SIGTRAP | P2001 | Core | Прерывание из-за трассировки/останова |
| SIGTTIN | P1990 | Stop | Ввод с терминала для фонового процесса |
| SIGTTOU | P1990 | Stop | Вывод с терминала для фонового процесса |
| SIGUNUSED | - | Core | Синоним SIGSYS |
| SIGURG | P2001 | Ign | Требующее внимание условие сокета (4.2BSD) |
| SIGUSR1 | P1990 | Term | Определяемый пользователем сигнал 1 |
| SIGUSR2 | P1990 | Term | Определяемый пользователем сигнал 2 |
| SIGVTALRM | P2001 | Term | Виртуальный будильник (4.2BSD) |
| SIGXCPU | P2001 | Core | Превышен предел процессорного времени (4.2BSD); |
| смотрите setrlimit(2) | |||
| SIGXFSZ | P2001 | Core | Превышен предел размера файла (4.2BSD); |
| смотрите setrlimit(2) | |||
| SIGWINCH | - | Ign | Сигнал изменения размера окна (4.3BSD, Sun) |
Сигналы SIGKILL и SIGSTOP нельзя поймать, заблокировать или проигнорировать.
В Linux до версии 2.2 включительно поведением по умолчанию для сигналов SIGSYS, SIGXCPU, SIGXFSZ и SIGBUS (на всех архитектурах кроме SPARC и MIPS) было завершение процесса без создания дампа (в некоторых системах UNIX действием по умолчанию для SIGXCPU и SIGXFSZ является завершение процесса без создания дампа). Linux версии 2.4 соответствует требованиям POSIX.1-2001 для этих сигналов и завершает процесс с созданием дампа.
Сигнал SIGEMT не определён в POSIX.1-2001, но, тем не менее, появляется почти во всех системах UNIX, где действием по умолчанию для него является завершение процесса с созданием дампа.
Сигнал SIGPWR (не определён в POSIX.1-2001) по умолчанию, обычно, игнорируется (в других системах UNIX).
Для сигнала SIGIO (не определён в POSIX.1-2001) в других системах UNIX действием по умолчанию является игнорирование.
Числовое значение каждого сигнала показано в таблице ниже. У многих сигналов номера различаются на разных архитектурах. Первое числовое значение в каждой строке таблицы описывает номер сигнала на x86, ARM и большинстве других архитектур; второе значение для Alpha и SPARC, третье для MIPS, последнее для PARISC. Символ минус (-) означает, что сигнал отсутствует в соответствующей архитектуре.
| Сигнал | x86/ARM | Alpha/ | MIPS | PARISC | Примечания |
| большинство других | SPARC | ||||
| SIGHUP | 1 | 1 | 1 | 1 | |
| SIGINT | 2 | 2 | 2 | 2 | |
| SIGQUIT | 3 | 3 | 3 | 3 | |
| SIGILL | 4 | 4 | 4 | 4 | |
| SIGTRAP | 5 | 5 | 5 | 5 | |
| SIGABRT | 6 | 6 | 6 | 6 | |
| SIGIOT | 6 | 6 | 6 | 6 | |
| SIGBUS | 7 | 10 | 10 | 10 | |
| SIGEMT | - | 7 | 7 | - | |
| SIGFPE | 8 | 8 | 8 | 8 | |
| SIGKILL | 9 | 9 | 9 | 9 | |
| SIGUSR1 | 10 | 30 | 16 | 16 | |
| SIGSEGV | 11 | 11 | 11 | 11 | |
| SIGUSR2 | 12 | 31 | 17 | 17 | |
| SIGPIPE | 13 | 13 | 13 | 13 | |
| SIGALRM | 14 | 14 | 14 | 14 | |
| SIGTERM | 15 | 15 | 15 | 15 | |
| SIGSTKFLT | 16 | - | - | 7 | |
| SIGCHLD | 17 | 20 | 18 | 18 | |
| SIGCLD | - | - | 18 | - | |
| SIGCONT | 18 | 19 | 25 | 26 | |
| SIGSTOP | 19 | 17 | 23 | 24 | |
| SIGTSTP | 20 | 18 | 24 | 25 | |
| SIGTTIN | 21 | 21 | 26 | 27 | |
| SIGTTOU | 22 | 22 | 27 | 28 | |
| SIGURG | 23 | 16 | 21 | 29 | |
| SIGXCPU | 24 | 24 | 30 | 12 | |
| SIGXFSZ | 25 | 25 | 31 | 30 | |
| SIGVTALRM | 26 | 26 | 28 | 20 | |
| SIGPROF | 27 | 27 | 29 | 21 | |
| SIGWINCH | 28 | 28 | 20 | 23 | |
| SIGIO | 29 | 23 | 22 | 22 | |
| SIGPOLL | Тот же, что SIGIO | ||||
| SIGPWR | 30 | 29/- | 19 | 19 | |
| SIGINFO | - | 29/- | - | - | |
| SIGLOST | - | -/29 | - | - | |
| SIGSYS | 31 | 12 | 12 | 31 | |
| SIGUNUSED | 31 | - | - | 31 |
Также заметим следующее:
Начиная с версии 2.2, Linux поддерживает сигналы реального времени согласно первоначальному описанию расширений реального времени в POSIX.1b (теперь включено в POSIX.1-2001). Диапазон поддерживаемых сигналов реального времени определяется макросами SIGRTMIN и SIGRTMAX. Согласно POSIX.1-2001 требуется, чтобы реализация поддерживала не менее _POSIX_RTSIG_MAX (8) сигналов реального времени.
Ядро Linux поддерживает 33 таких сигнала, начиная с номера 32 до номера 64. Однако внутри реализации нитей POSIX в glibc используется два (для NPTL) или три (для LinuxThreads) сигнала реального времени (смотрите pthreads(7)), а значение SIGRTMIN корректируется должным образом (до 34 или 35). Так как диапазон доступных сигналов реального времени различается в зависимости от реализации нитей в glibc (и это может происходить во время выполнения при смене ядра и glibc), и, более того, диапазон сигналов реального времени различен в разных системах UNIX, то программы никогда не должны задавать сигналы реального времени по номерам, а вместо этого всегда должны записывать их в виде SIGRTMIN+n и выполнять проверку (во время выполнения), что SIGRTMIN+n не превышает SIGRTMAX.
В отличие от стандартных сигналов, сигналы реального времени не имеют предопределенного назначения: весь набор сигналов реального времени приложения могут использовать так, как им нужно.
Действием по умолчанию для необработанных сигналов реального времени является завершение процесса (terminate).
Сигналы реального времени отличаются от обычных в следующем:
Если процессу передан и стандартный сигнал, и сигнал реального времени, то в POSIX однозначно не определено, какой из них будет доставлен первым. В Linux, как и во многих других реализациях в таких случаях, отдан приоритет стандартным сигналам.
В соответствии с POSIX, реализация должна позволять ставить в очередь процесса, как минимум, _POSIX_SIGQUEUE_MAX (32) сигнала реального времени. Однако в Linux это делается по-другому. В ядрах до версии 2.6.7 включительно, Linux накладывает общесистемный лимит на количество сигналов режима реального времени в очереди для всех процессов. Этот лимит может быть получен и изменён (если есть права) через файл /proc/sys/kernel/rtsig-max. Текущее количество сигналов режима реального времени в очереди можно получить из файла /proc/sys/kernel/rtsig-nr. В Linux 2.6.8 данные интерфейсы /proc были заменены на ограничение ресурса RLIMIT_SIGPENDING, которое устанавливает ограничение на очередь сигналов на каждого пользователя отдельно; дополнительную информацию можно найти в setrlimit(2).
Для дополнительных сигналов реального времени требуется расширение структуры набора сигналов (sigset_t) с 32 до 64 бит. В связи с этим, различные системные вызовы заменены на новые системные вызов, поддерживающие набор сигналов большего размера. Вот соответствие старых и новых системных вызовов:
| Linux версии 2.0 и более ранние | Linux версии 2.2 и новее |
| sigaction(2) | rt_sigaction(2) |
| sigpending(2) | rt_sigpending(2) |
| sigprocmask(2) | rt_sigprocmask(2) |
| sigreturn(2) | rt_sigreturn(2) |
| sigsuspend(2) | rt_sigsuspend(2) |
| sigtimedwait(2) | rt_sigtimedwait(2) |
Если обработчик сигнала вызван во время заблокированного системного вызова или библиотечной функции, то может произойти следующее:
Выбираемое поведение зависит от интерфейса и от того, был ли обработчик сигнала установлен с флагом SA_RESTART (смотрите sigaction(2)). Но в различных системах UNIX есть другие различия; далее описаны подробности для Linux.
Если заблокированный вызов к одному из следующих интерфейсов прерван обработчиком сигнала, то вызов автоматически перезапускается после завершения обработчика сигнала, если задействован флаг SA_RESTART; иначе вызов завершается ошибкой EINTR:
Следующие интерфейсы никогда не перезапускаются после прерывания обработчиком сигнала независимо от наличия SA_RESTART; они всегда завершаются с ошибкой EINTR, если прерываются обработчиком сигнала:
Функция sleep(3) также никогда не перезапускается, если прервана обработчиком сигнала, но сообщает об успешном выполнении: возвращает количество оставшиеся для сна секунд.
В Linux, даже в отсутствии обработчиков сигнала, некоторые блокирующие интерфейсы могут завершаться с ошибкой EINTR, если процесс останавливается одним из сигналов останова и затем возобновляет работу при получении сигнала SIGCONT. Такое поведение не предусмотрено POSIX.1 и в других системах отсутствует.
Интерфейсы Linux, к которым это относится:
POSIX.1, кроме описанных исключений.
Описание безопасных асинхронных функций при работе с сигналами смотрите в signal-safety(7).
kill(1), clone(2), getrlimit(2), kill(2), restart_syscall(2), rt_sigqueueinfo(2), setitimer(2), setrlimit(2), sgetmask(2), sigaction(2), sigaltstack(2), signal(2), signalfd(2), sigpending(2), sigprocmask(2), sigreturn(2), sigsuspend(2), sigwaitinfo(2), abort(3), bsd_signal(3), killpg(3), longjmp(3), pthread_sigqueue(3), raise(3), sigqueue(3), sigset(3), sigsetops(3), sigvec(3), sigwait(3), strsignal(3), sysv_signal(3), core(5), proc(5), nptl(7), pthreads(7), sigevent(7)
| 2019-03-06 | Linux |