SIGNAL(7) | Руководство программиста Linux | SIGNAL(7) |
ИМЯ¶
signal - обзор сигналов
ОПИСАНИЕ¶
В Linux поддерживаются надёжные (reliable) сигналы POSIX (далее, «стандартные сигналы») и сигналы реального времени POSIX.
Обработчики сигнала¶
Каждый сигнал имеет текущий обработчик, который определяет, что будет делать процесс при поступлении сигнала.
The entries in the "Action" column of the tables below specify the default disposition for each signal, as follows:
- Term
- Действие по умолчанию — завершение процесса.
- Ign
- Действие по умолчанию — игнорирование сигнала.
- Core
- Действие по умолчанию — завершение процесса и вывод дампа в файл (смотрите core(5)).
- Stop
- Действие по умолчанию — остановка процесса.
- Cont
- Действие по умолчанию — продолжение работы процесса, если он в данный момент остановлен.
A process can change the disposition of a signal using sigaction(2) or signal(2). (The latter is less portable when establishing a signal handler; see signal(2) for details.) Using these system calls, a process can elect one of the following behaviors to occur on delivery of the signal: perform the default action; ignore the signal; or catch the signal with a signal handler, a programmer-defined function that is automatically invoked when the signal is delivered. (By default, the signal handler is invoked on the normal process stack. It is possible to arrange that the signal handler uses an alternate stack; see sigaltstack(2) for a discussion of how to do this and when it might be useful.)
Реакция на сигналы является атрибутом процесса: в многонитевом приложении реакция на определённый сигнал одинакова для всех нитей.
Потомок, созданный с помощью fork(2), наследует реакцию на сигналы от своего родителя. При execve(2) реакция на сигналы устанавливается в значение по умолчанию; реакция на игнорируемые сигналы не изменяется.
Отправка сигнала¶
Для отправки сигнала можно использовать следующие системные вызовы и библиотечные функции:
- raise(3)
- Посылает сигнал вызвавшей нити.
- kill(2)
- Посылает сигнал указанному процессу, всем членам указанной группы процессов или всем процессам в системе.
- killpg(3)
- Посылает сигнал всем членам указанной группы процессов.
- pthread_kill(3)
- Посылает сигнал указанной нити POSIX в том же процессе, что и вызывающий.
- tgkill(2)
- Посылает сигнал указанной нити в указанном процессе (данный системный вызов используется в реализации pthread_kill(3)).
- sigqueue(3)
- Посылает сигнал реального времени указанному процессу с сопроводительными данными.
Ожидание сигнала для обработки¶
The following system calls suspend execution of the calling process or thread until a signal is caught (or an unhandled signal terminates the process):
- pause(2)
- Приостанавливает выполнение до тех пор, пока не будет пойман любой сигнал.
- sigsuspend(2)
- Временно изменяет маску сигналов (смотрите далее) и приостанавливает выполнение до получения одного из незамаскированных сигналов.
Синхронный приём сигнала¶
В отличие от асинхронного получения сигнала через обработчик, возможно синхронно получить сигнал, то есть блокировать выполнение до поступления сигнала в некоторой точке, в которой ядро вернёт информацию о сигнале вызывающему. Для этого существует два пути:
- С помощью sigwaitinfo(2), sigtimedwait(2) и sigwait(3). Они приостанавливают выполнение до поступления одного из заданного набора сигналов. Каждый из этих вызовов возвращает информацию о полученном сигнале.
- С помощью signalfd(2). Данный вызов возвращает файловый дескриптор, который можно использовать для чтения информации о сигналах, доставляемых вызывающему. Каждое выполнение read(2) с этим файловым дескриптором блокируется до тех пор, пока один из сигналов набора, указанного в вызове signalfd(2), не будет послан вызывающему. В возвращаемом read(2) буфере содержится структура, описывающая сигнал.
Сигнальная маска и ожидающие сигналы¶
Сигнал может быть заблокирован. Это означает, что он не будет доставлен до тех пор, пока не будет разблокирован. В промежуток времени от генерации сигнала и до его доставки о сигнале говорят как об ожидающем.
В каждой нити процесса имеется независимая сигнальная маска, определяющая набор сигналов, которые нить, в данный момент, блокирует. Нить может управлять сигнальной маской с помощью pthread_sigmask(3). В обычном однонитевом приложении для работы с сигнальной маской можно использовать вызов sigprocmask(2).
Потомок, создаваемый с помощью fork(2), наследует копию родительской маски сигналов; маска сигналов сохраняется при вызове execve(2).
A signal may be generated (and thus pending) for a process as a whole (e.g., when sent using kill(2)) or for a specific thread (e.g., certain signals, such as SIGSEGV and SIGFPE, generated as a consequence of executing a specific machine-language instruction are thread directed, as are signals targeted at a specific thread using pthread_kill(3)). A process-directed signal may be delivered to any one of the threads that does not currently have the signal blocked. If more than one of the threads has the signal unblocked, then the kernel chooses an arbitrary thread to which to deliver the signal.
Нить может получить набор сигналов, которые находятся в состоянии ожидания с помощью вызова sigpending(2). Этот набор будет состоять из объединения набора ожидающих сигналов, направленных процессу, и набора ожидающих сигналов для вызвавшей нити.
Потомок, созданный с помощью fork(2), первоначально имеет пустой набор ожидающих сигналов; набор ожидающих сигналов сохраняется при вызове execve(2).
Стандартные сигналы¶
Linux supports the standard signals listed below. Several signal numbers are architecture-dependent, as indicated in the "Value" column. (Where three values are given, the first one is usually valid for alpha and sparc, the middle one for x86, arm, and most other architectures, and the last one for mips. (Values for parisc are not shown; see the Linux kernel source for signal numbering on that architecture.) A dash (-) denotes that a signal is absent on the corresponding architecture.
First the signals described in the original POSIX.1-1990 standard.
Сигнал | Значение | Действие | Комментарий |
SIGHUP | 1 | Term | Обнаружен обрыв связи с управляющим |
терминалом, либо завершение управляющего терминалом процесса | |||
SIGINT | 2 | Term | Прерывание с клавиатуры |
SIGQUIT | 3 | Core | Выход с клавиатуры |
SIGILL | 4 | Core | Недопустимая инструкция |
SIGABRT | 6 | Core | Сигнал аварии (abort), посланный abort(3) |
SIGFPE | 8 | Core | Ошибка операций с плавающей запятой |
SIGKILL | 9 | Term | Kill-сигнал |
SIGSEGV | 11 | Core | Некорректная ссылка в память |
SIGPIPE | 13 | Term | Обрыв канала: запись в канал без |
читателей; смотрите pipe(7) | |||
SIGALRM | 14 | Term | Сигнал таймера, посланный alarm(2) |
SIGTERM | 15 | Term | Сигнал завершения |
SIGUSR1 | 30,10,16 | Term | Определяемый пользователем сигнал 1 |
SIGUSR2 | 31,12,17 | Term | Определяемый пользователем сигнал 2 |
SIGCHLD | 20,17,18 | Ign | Потомок остановлен или завершился |
SIGCONT | 19,18,25 | Cont | Продолжить, если остановлен |
SIGSTOP | 17,19,23 | Stop | Остановить процесс |
SIGTSTP | 18,20,24 | Stop | Останов введён с терминала |
SIGTTIN | 21,21,26 | Stop | Ввод с терминала для фонового процесса |
SIGTTOU | 22,22,27 | Stop | Вывод с терминала для фонового процесса |
Сигналы SIGKILL и SIGSTOP нельзя поймать, заблокировать или проигнорировать.
Next the signals not in the POSIX.1-1990 standard but described in SUSv2 and POSIX.1-2001.
Сигнал | Значение | Действие | Комментарий |
SIGBUS | 10,7,10 | Core | Ошибка шины (некорректный адрес доступа) |
SIGPOLL | Term | Опрашиваемое событие (Sys V) | |
Синоним SIGIO | |||
SIGPROF | 27,27,29 | Term | Время профилирования истекло |
SIGSYS | 12,31,12 | Core | Неправильный системный вызов (SVr4); |
смотрите также seccomp(2) | |||
SIGTRAP | 5 | Core | Прерывание из-за трассировки/останова |
SIGURG | 16,23,21 | Ign | Требующее внимание условие сокета (4.2BSD) |
SIGVTALRM | 26,26,28 | Term | Виртуальный будильник (4.2BSD) |
SIGXCPU | 24,24,30 | Core | Превышен предел процессорного времени (4.2BSD); |
смотрите setrlimit(2) | |||
SIGXFSZ | 25,25,31 | Core | Превышен предел размера файла (4.2BSD); |
смотрите setrlimit(2) |
В Linux до версии 2.2 включительно поведением по умолчанию для сигналов SIGSYS, SIGXCPU, SIGXFSZ и SIGBUS (на всех архитектурах кроме SPARC и MIPS) было завершение процесса без создания дампа (в некоторых системах UNIX действием по умолчанию для SIGXCPU и SIGXFSZ является завершение процесса без создания дампа). Linux версии 2.4 соответствует требованиям POSIX.1-2001 для этих сигналов и завершает процесс с созданием дампа.
Next various other signals.
Сигнал | Значение | Действие | Комментарий |
SIGIOT | 6 | Core | Ловушка IOT. Синоним SIGABRT |
SIGEMT | 7,-,7 | Term | Ловушка эмулятора |
SIGSTKFLT | -,16,- | Term | Ошибка стека на сопроцессоре (не используется) |
SIGIO | 23,29,22 | Term | Теперь возможен ввод/вывод (4.2BSD) |
SIGCLD | -,-,18 | Ign | Синоним SIGCHLD |
SIGPWR | 29,30,19 | Term | Отказ питания (System V) |
SIGINFO | 29,-,- | Синоним SIGPWR | |
SIGLOST | -,-,- | Term | Утрачена блокировка файла (не используется) |
SIGWINCH | 28,28,20 | Ign | Сигнал изменения размера окна (4.3BSD, Sun) |
SIGUNUSED | -,31,- | Core | Синоним SIGSYS |
(Signal 29 is SIGINFO / SIGPWR on an alpha but SIGLOST on a sparc.)
Сигнал SIGEMT не определён в POSIX.1-2001, но, тем не менее, появляется почти во всех системах UNIX, где действием по умолчанию для него является завершение процесса с созданием дампа.
Сигнал SIGPWR (не определён в POSIX.1-2001) по умолчанию, обычно, игнорируется (в других системах UNIX).
Для сигнала SIGIO (не определён в POSIX.1-2001) в других системах UNIX действием по умолчанию является игнорирование.
Where defined, SIGUNUSED is synonymous with SIGSYS on most architectures. Since glibc 2.26, SIGUNUSED is no longer defined on any architecture.
Сигналы реального времени¶
Начиная с версии 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).
Сигналы реального времени отличаются от обычных в следующем:
- 1.
- В очередь можно добавлять несколько экземпляров одного сигнала реального времени. В случае со стандартными сигналами, если доставляется несколько экземпляров сигнала, в то время как этот тип сигнала в данный момент заблокирован, то только один экземпляр будет добавлен в очередь.
- 2.
- Если сигнал отправляется с помощью sigqueue(3), то с сигналом может быть отправлено некоторое значение (целочисленное, либо указатель). Если принимающий процесс устанавливает обработчик для сигнала, используя флаг SA_SIGINFO и вызов sigaction(2), то он может получить это значение через поле si_value структуры siginfo_t, переданной обработчику в виде второго аргумента. Кроме этого, поля si_pid и si_uid данной структуры можно использовать для получения идентификатора процесса и реального идентификатора пользователя, отправившего сигнал.
- 3.
- Сигналы реального времени доставляются точно в порядке поступления. Несколько сигналов одного типа доставляются в порядке, определяемых их отправлением. Если процессу отправлено несколько разных сигналов реального времени, то порядок их доставки начинается с сигнала с наименьшим номером (то есть сигналы с наименьшим номером имеют наивысший приоритет). Порядок же для стандартных сигналов в такой ситуации не определён.
Если процессу передан и стандартный сигнал, и сигнал реального времени, то в 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) |
Прерывание системных вызовов и библиотечных функций обработчиками сигналов¶
Если обработчик сигнала вызван во время заблокированного системного вызова или библиотечной функции, то может произойти следующее:
- вызов автоматически перезапускается после возврата из обработчика сигнала; или
- вызов завершается с ошибкой EINTR.
Выбираемое поведение зависит от интерфейса и от того, был ли обработчик сигнала установлен с флагом SA_RESTART (смотрите sigaction(2)). Но в различных системах UNIX есть другие различия; далее описаны подробности для Linux.
Если заблокированный вызов к одному из следующих интерфейсов прерван обработчиком сигнала, то вызов автоматически перезапускается после завершения обработчика сигнала, если задействован флаг SA_RESTART; иначе вызов завершается ошибкой EINTR:
- Вызовы read(2), readv(2), write(2), writev(2) и ioctl(2) для «медленных» устройств. «Медленным» называют устройство, которое может навсегда заблокировать ввод-вывод, например, терминал, канал или сокет. Если вызов ввода-вывода для медленного устройства уже передал немного данных на момент прерывания обработчиком сигнала, то вызов вернёт состояние успешного выполнения (обычно, количество переданных байт). Заметим, что диск (локальный) не подходит под определение медленного устройства; операции ввода-вывода с дисками не прерываются сигналами.
- Вызов open(2), если он может выполнить блокировку (например, при открытии FIFO; смотрите fifo(7)).
- Вызовы wait(2), wait3(2), wait4(2), waitid(2) и waitpid(2).
- Интерфейсы сокетов: accept(2), connect(2), recv(2), recvfrom(2), recvmmsg(2), recvmsg(2), send(2), sendto(2) и sendmsg(2), если для сокета не указано время ожидания (смотрите далее).
- Интерфейсы файловой блокировки: flock(2) и операции F_SETLKW и F_OFD_SETLKW у fcntl(2).
- Интерфейсы очереди сообщений POSIX: mq_receive(3), mq_timedreceive(3), mq_send(3) и mq_timedsend(3).
- Вызов futex(2) с FUTEX_WAIT (начиная с Linux 2.6.22; до этой версии вызов завершался с ошибкой EINTR).
- getrandom(2).
- pthread_mutex_lock(3), pthread_cond_wait(3) связанный с этим программный интерфейс.
- futex(2) FUTEX_WAIT_BITSET.
- Интерфейсы семафоров POSIX: sem_wait(3) и sem_timedwait(3) (начиная с Linux 2.6.22; до этой версии вызовы завершались с ошибкой EINTR).
- Вызов read(2) из файлового дескриптора inotify(7) (начиная с Linux 3.8; прежде всегда завершался с ошибкой EINTR).
Следующие интерфейсы никогда не перезапускаются после прерывания обработчиком сигнала независимо от наличия SA_RESTART; они всегда завершаются с ошибкой EINTR, если прерываются обработчиком сигнала:
- «Входные» интерфейсы сокетов, если установлен таймаут (SO_RCVTIMEO) на сокете с помощью setsockopt(2): accept(2), recv(2), recvfrom(2), recvmmsg(2) (также с аргументом timeout, не равным NULL) и recvmsg(2).
- «Выходные» интерфейсы сокетов, если установлен таймаут (SO_RCVTIMEO) на сокете с помощью setsockopt(2): connect(2), send(2), sendto(2) и sendmsg(2).
- Интерфейсы, используемые для ожидания сигналов: pause(2), sigsuspend(2), sigtimedwait(2) и sigwaitinfo(2).
- Интерфейсы комбинирования (multiplexing) файловых дескрипторов: epoll_wait(2), epoll_pwait(2), poll(2), ppoll(2), select(2) и pselect(2).
- IPC-интерфейсы System V: msgrcv(2), msgsnd(2), semop(2) и semtimedop(2).
- Интерфейсы сна: clock_nanosleep(2), nanosleep(2) и usleep(3).
- io_getevents(2).
Функция sleep(3) также никогда не перезапускается, если прервана обработчиком сигнала, но сообщает об успешном выполнении: возвращает количество оставшиеся для сна секунд.
Прерывание системных вызовов и библиотечных функций сигналами останова¶
В Linux, даже в отсутствии обработчиков сигнала, некоторые блокирующие интерфейсы могут завершаться с ошибкой EINTR, если процесс останавливается одним из сигналов останова и затем возобновляет работу при получении сигнала SIGCONT. Такое поведение не предусмотрено POSIX.1 и в других системах отсутствует.
Интерфейсы Linux, к которым это относится:
- «Входные» интерфейсы сокетов, если установлен таймаут (SO_RCVTIMEO) на сокете с помощью setsockopt(2): accept(2), recv(2), recvfrom(2), recvmmsg(2) (также с аргументом timeout, не равным NULL) и recvmsg(2).
- «Выходные» интерфейсы сокетов, если установлен таймаут (SO_RCVTIMEO) на сокете с помощью setsockopt(2): connect(2), send(2), sendto(2) и sendmsg(2), если установлен таймаут отправления (SO_SNDTIMEO).
- epoll_wait(2), epoll_pwait(2).
- semop(2), semtimedop(2).
- sigtimedwait(2), sigwaitinfo(2).
- Linux 3.7 и старее: read(2) из файлового дескриптора inotify(7)
- Linux версии 2.6.21 и более ранних: futex(2) с FUTEX_WAIT, sem_timedwait(3), sem_wait(3).
- Linux версии 2.6.8 и более ранних: msgrcv(2), msgsnd(2).
- Linux версии 2.4 и более ранних: nanosleep(2).
СООТВЕТСТВИЕ СТАНДАРТАМ¶
POSIX.1, кроме описанных исключений.
ЗАМЕЧАНИЯ¶
Описание безопасных асинхронных функций при работе с сигналами смотрите в signal-safety(7).
СМ. ТАКЖЕ¶
kill(1), 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)
ЗАМЕЧАНИЯ¶
Эта страница является частью проекта Linux man-pages версии 4.16. Описание проекта, информацию об ошибках и последнюю версию этой страницы можно найти по адресу https://www.kernel.org/doc/man-pages/.
ПЕРЕВОД¶
Русский перевод этой страницы руководства был сделан 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>
Этот перевод является бесплатной документацией; прочитайте Стандартную общественную лицензию GNU версии 3 или более позднюю, чтобы узнать об условиях авторского права. Мы не несем НИКАКОЙ ОТВЕТСТВЕННОСТИ.
Если вы обнаружите ошибки в переводе этой страницы руководства, пожалуйста, отправьте электронное письмо на man-pages-ru-talks@lists.sourceforge.net.
15 сентября 2017 г. | Linux |