signal - обзор
сигналов
В Linux
поддерживаются
надёжные (reliable)
сигналы POSIX
(далее,
«стандартные
сигналы») и
сигналы
реального
времени POSIX.
Каждый
сигнал
имеет
текущий
обработчик,
который
определяет,
что будет
делать
процесс
при
поступлении
сигнала.
В таблице
далее есть
столбец
«Действие»,
в котором
указан
обработчик
по
умолчанию
для
каждого
сигнала:
- Term
- Действие
по
умолчанию
—
завершение
процесса.
- Ign
- Действие
по
умолчанию
—
игнорирование
сигнала.
- Core
- Действие
по
умолчанию
—
завершение
процесса и
вывод
дампа в
файл
(смотрите
core(5)).
- Stop
- Действие
по
умолчанию
—
остановка
процесса.
- Cont
- Действие
по
умолчанию
—
продолжение
работы
процесса,
если он в
данный
момент
остановлен.
Процесс
может
изменить
обработчик
сигнала с
помощью
sigaction(2)
или
signal(2)
(последний
менее
переносим,
если
используется
для
установки
обработчика
сигнала;
дополнительную
информацию
смотрите в
signal(2)).
Используя
данные
системные
вызовы
процесс
может
выбрать
одно из
следующих
действий
при
получении
сигнала:
выполнить
действие
по
умолчанию,
игнорировать
сигнал,
поймать
сигнал
обработчиком
сигнала —
функцией,
задаваемой
программистом,
которая
автоматически
вызывается
при
получении
сигнала.
По
умолчанию
обработчик
сигнала
использует
обычный
стек
процесса.
Возможно
сделать
так, чтобы
обработчик
сигнала
использовал
альтернативный
стек; как
это
делается и
когда это
может быть
полезно
смотрите в
sigaltstack(2).
Реакция на
сигналы
является
атрибутом
процесса: в
многонитевом
приложении
реакция на
определённый
сигнал
одинакова
для всех
нитей.
Потомок,
созданный
с помощью
fork(2),
наследует
реакцию на
сигналы от
своего
родителя.
При
execve(2)
реакция на
сигналы
устанавливается
в значение
по
умолчанию;
реакция на
игнорируемые
сигналы не
изменяется.
Для
отправки
сигнала
можно
использовать
следующие
системные
вызовы и
библиотечные
функции:
-
raise(3)
- Посылает
сигнал
вызвавшей
нити.
-
kill(2)
- Посылает
сигнал
указанному
процессу,
всем
членам
указанной
группы
процессов
или всем
процессам
в системе.
-
pidfd_send_signal(2)
- Sends a signal to a process identified by a PID file
descriptor.
-
killpg(3)
- Посылает
сигнал
всем
членам
указанной
группы
процессов.
-
pthread_kill(3)
- Посылает
сигнал
указанной
нити POSIX в том
же
процессе,
что и
вызывающий.
-
tgkill(2)
- Посылает
сигнал
указанной
нити в
указанном
процессе
(данный
системный
вызов
используется
в
реализации
pthread_kill(3)).
-
sigqueue(3)
- Посылает
сигнал
реального
времени
указанному
процессу с
сопроводительными
данными.
Следующие
системные
вызовы
приостанавливают
выполнение
вызывающей
нити до тех
пор, пока не
будет
пойман
сигнал (или
необработанный
сигнал не
завершит
процесс):
-
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 process-directed or thread-directed. A process-directed signal
is one that is targeted at (and thus pending for) the process as a whole. A
signal may be process-directed because it was generated by the kernel for
reasons other than a hardware exception, or because it was sent using
kill(2) or
sigqueue(3). A thread-directed signal is one that is
targeted at a specific thread. A signal may be thread-directed because it was
generated as a consequence of executing a specific machine-language
instruction that triggered a hardware exception (e.g.,
SIGSEGV for an
invalid memory access, or
SIGFPE for a math error), or because it was
targeted at a specific thread using interfaces such as
tgkill(2) or
pthread_kill(3).
Направленный
процессу
сигнал
может быть
доставлен
в любую из
нитей, у
которой
сигнал не
заблокирован.
Если
имеется
несколько
таких
нитей, то
ядро
выбирает
произвольную
нить,
которой и
доставит
сигнал.
Нить может
получить
набор
сигналов,
которые
находятся
в
состоянии
ожидания с
помощью
вызова
sigpending(2).
Этот набор
будет
состоять
из
объединения
набора
ожидающих
сигналов,
направленных
процессу, и
набора
ожидающих
сигналов
для
вызвавшей
нити.
Потомок,
созданный
с помощью
fork(2),
первоначально
имеет
пустой
набор
ожидающих
сигналов;
набор
ожидающих
сигналов
сохраняется
при вызове
execve(2).
Whenever there is a transition from kernel-mode to user-mode execution (e.g., on
return from a system call or scheduling of a thread onto the CPU), the kernel
checks whether there is a pending unblocked signal for which the process has
established a signal handler. If there is such a pending signal, the following
steps occur:
- (1)
- The kernel performs the necessary preparatory steps for
execution of the signal handler:
- (1.1)
- The signal is removed from the set of pending signals.
- (1.2)
- If the signal handler was installed by a call to
sigaction(2) that specified the SA_ONSTACK flag and the
thread has defined an alternate signal stack (using
sigaltstack(2)), then that stack is installed.
- (1.3)
- Various pieces of signal-related context are saved into a
special frame that is created on the stack. The saved information
includes:
- •
- the program counter register (i.e., the address of the next
instruction in the main program that should be executed when the signal
handler returns);
- •
- architecture-specific register state required for resuming
the interrupted program;
- •
- the thread's current signal mask;
- •
- the thread's alternate signal stack settings.
- (If the signal handler was installed using the
sigaction(2) SA_SIGINFO flag, then the above information is
accessible via the ucontext_t object that is pointed to by the
third argument of the signal handler.)
- (1.4)
- Any signals specified in act->sa_mask when
registering the handler with sigprocmask(2) are added to the
thread's signal mask. The signal being delivered is also added to the
signal mask, unless SA_NODEFER was specified when registering the
handler. These signals are thus blocked while the handler executes.
- (2)
- The kernel constructs a frame for the signal handler on the
stack. The kernel sets the program counter for the thread to point to the
first instruction of the signal handler function, and configures the
return address for that function to point to a piece of user-space code
known as the signal trampoline (described in sigreturn(2)).
- (3)
- The kernel passes control back to user-space, where
execution commences at the start of the signal handler function.
- (4)
- When the signal handler returns, control passes to the
signal trampoline code.
- (5)
- The signal trampoline calls sigreturn(2), a system
call that uses the information in the stack frame created in step 1 to
restore the thread to its state before the signal handler was called. The
thread's signal mask and alternate signal stack settings are restored as
part of this procedure. Upon completion of the call to
sigreturn(2), the kernel transfers control back to user space, and
the thread recommences execution at the point where it was interrupted by
the signal handler.
Note that if the signal handler does not return (e.g., control is transferred
out of the handler using
siglongjmp(3), or the handler executes a new
program with
execve(2)), then the final step is not performed. In
particular, in such scenarios it is the programmer's responsibility to restore
the state of the signal mask (using
sigprocmask(2)), if it is desired
to unblock the signals that were blocked on entry to the signal handler. (Note
that
siglongjmp(3) may or may not restore the signal mask, depending on
the
savesigs value that was specified in the corresponding call to
sigsetjmp(3).)
From the kernel's point of view, execution of the signal handler code is exactly
the same as the execution of any other user-space code. That is to say, the
kernel does not record any special state information indicating that the
thread is currently executing inside a signal handler. All necessary state
information is maintained in user-space registers and the user-space stack.
The depth to which nested signal handlers may be invoked is thus limited only
by the user-space stack (and sensible software design!).
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 |
Pollable event (Sys V); |
|
|
|
synonym for 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
действием
по
умолчанию
является
игнорирование.
Если
несколько
стандартных
сигналов
ожидают
обработки
процессом,
то порядок
доставки
сигналов
не
определён.
Стандартные
сигналы не
упорядочиваются.
Если
генерируется
несколько
экземпляров
стандартного
сигнала
заблокированному
процессу,
то только
один
экземпляр
сигнала
помечается
как
ожидающий
(и сигнал
будет
доставлен
только
после
разблокировки).
В случае,
если уже
есть
ожидающий
стандартный
сигнал,
структура
siginfo_t
(смотрите
sigaction(2)),
связанная
с этим
сигналом,
не
перезаписывается
при
поступлении
последующих
экземпляров
того же
сигнала. То
есть,
процесс
получит
информацию,
связанную
с первым
экземпляром
сигнала.
Числовое
значение
каждого
сигнала
показано в
таблице
ниже. У
многих
сигналов
номера
различаются
на разных
архитектурах.
Первое
числовое
значение в
каждой
строке
таблицы
описывает
номер
сигнала на 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 |
|
Также
заметим
следующее:
- •
- Если
определён
сигнал SIGUNUSED,
то он
является
синонимом
SIGSYS. Начиная
с glibc 2.26,
определение
SIGUNUSED удалено
из всех
архитектур.
- •
- Сигнал с
номером 29
на Alpha
соответствует
SIGINFO/SIGPWR
(одинаковый
номер), а на SPARC
соответствует
SIGLOST.
Starting with Linux 2.2, Linux supports real-time signals as originally defined
in the POSIX.1b real-time extensions (and now included in POSIX.1-2001). The
range of supported real-time signals is defined by the macros
SIGRTMIN
and
SIGRTMAX. POSIX.1-2001 requires that an implementation support at
least
_POSIX_RTSIG_MAX (8) real-time signals.
Ядро Linux
поддерживает
33 таких
сигнала,
начиная с
номера 32 до
номера 64.
Однако
внутри
реализации
нитей POSIX в glibc
используется
два (для NPTL)
или три (для
LinuxThreads) сигнала
реального
времени
(смотрите
pthreads(7)), а
значение
SIGRTMIN
корректируется
должным
образом (до 34
или 35). Так
как
диапазон
доступных
сигналов
реального
времени
различается
в
зависимости
от
реализации
нитей в glibc (и
это может
происходить
во время
выполнения
при смене
ядра и glibc), и,
более того,
диапазон
сигналов
реального
времени
различен в
разных
системах UNIX,
то
программы
никогда не
должны
задавать
сигналы
реального
времени по
номерам, а
вместо
этого
всегда
должны
записывать
их в виде
SIGRTMIN+n
и
выполнять
проверку
(во время
выполнения),
что
SIGRTMIN+n не
превышает
SIGRTMAX.
В отличие
от
стандартных
сигналов,
сигналы
реального
времени не
имеют
предопределенного
назначения:
весь набор
сигналов
реального
времени
приложения
могут
использовать
так, как им
нужно.
Действием
по
умолчанию
для
необработанных
сигналов
реального
времени
является
завершение
процесса (terminate).
Сигналы
реального
времени
отличаются
от обычных
в
следующем:
- •
- В
очередь
можно
добавлять
несколько
экземпляров
одного
сигнала
реального
времени. В
случае со
стандартными
сигналами,
если
доставляется
несколько
экземпляров
сигнала, в
то время
как этот
тип
сигнала в
данный
момент
заблокирован,
то только
один
экземпляр
будет
добавлен в
очередь.
- •
- Если
сигнал
отправляется
с помощью
sigqueue(3), то с
сигналом
может быть
отправлено
некоторое
значение
(целочисленное,
либо
указатель).
Если
принимающий
процесс
устанавливает
обработчик
для
сигнала,
используя
флаг SA_SIGINFO и
вызов sigaction(2),
то он может
получить
это
значение
через поле
si_value
структуры
siginfo_t,
переданной
обработчику
в виде
второго
аргумента.
Кроме
этого, поля
si_pid и si_uid
данной
структуры
можно
использовать
для
получения
идентификатора
процесса и
реального
идентификатора
пользователя,
отправившего
сигнал.
- •
- Сигналы
реального
времени
доставляются
точно в
порядке
поступления.
Несколько
сигналов
одного
типа
доставляются
в порядке,
определяемых
их
отправлением.
Если
процессу
отправлено
несколько
разных
сигналов
реального
времени, то
порядок их
доставки
начинается
с сигнала с
наименьшим
номером (то
есть
сигналы с
наименьшим
номером
имеют
наивысший
приоритет).
Порядок же
для
стандартных
сигналов в
такой
ситуации
не
определён.
Если
процессу
передан и
стандартный
сигнал, и
сигнал
реального
времени, то
в POSIX
однозначно
не
определено,
какой из
них будет
доставлен
первым. В Linux,
как и во
многих
других
реализациях
в таких
случаях,
отдан
приоритет
стандартным
сигналам.
According to POSIX, an implementation should permit at least
_POSIX_SIGQUEUE_MAX (32) real-time signals to be queued to a process.
However, Linux does things differently. Up to and including Linux 2.6.7, Linux
imposes a system-wide limit on the number of queued real-time signals for all
processes. This limit can be viewed and (with privilege) changed via the
/proc/sys/kernel/rtsig-max file. A related file,
/proc/sys/kernel/rtsig-nr, can be used to find out how many real-time
signals are currently queued. In Linux 2.6.8, these
/proc interfaces
were replaced by the
RLIMIT_SIGPENDING resource limit, which specifies
a per-user limit for queued signals; see
setrlimit(2) for further
details.
Для
дополнительных
сигналов
реального
времени
требуется
расширение
структуры
набора
сигналов (
sigset_t) с 32 до 64 бит.
В связи с
этим,
различные
системные
вызовы
заменены
на новые
системные
вызов,
поддерживающие
набор
сигналов
большего
размера.
Вот
соответствие
старых и
новых
системных
вызовов:
Если
обработчик
сигнала
вызван во
время
заблокированного
системного
вызова или
библиотечной
функции, то
может
произойти
следующее:
- •
- вызов
автоматически
перезапускается
после
возврата
из
обработчика
сигнала;
или
- •
- вызов
завершается
с ошибкой
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)
также
никогда не
перезапускается,
если
прервана
обработчиком
сигнала, но
сообщает
об
успешном
выполнении:
возвращает
количество
оставшиеся
для сна
секунд.
In certain circumstances, the
seccomp(2) user-space notification feature
can lead to restarting of system calls that would otherwise never be restarted
by
SA_RESTART; for details, see
seccomp_unotify(2).
В 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).
В файле
/proc/[pid]/task/[tid]/status
содержатся
различные
поля о
сигналах,
которые
нить
блокирует (
SigBlk), ловит (
SigCgt)
или
игнорирует
(
SigIgn). Набор
отлавливаемые
или
игнорируемых
сигналов
одинаков
для всех
нитей
процесса.
Остальные
поля
отражают
набор
ожидающих
сигналов,
которые
непосредственно
направляются
нити (
SigPnd), а
также
набор
ожидающих
сигналов,
которые
направляются
непосредственно
процессу (
ShdPnd).
Соответствующие
поля в
/proc/[pid]/status
содержат
информацию
для
главной
нити.
Дополнительную
информацию
смотрите в
proc(5).
There are six signals that can be delivered as a consequence of a hardware
exception:
SIGBUS,
SIGEMT,
SIGFPE,
SIGILL,
SIGSEGV, and
SIGTRAP. Which of these signals is delivered, for
any given hardware exception, is not documented and does not always make
sense.
For example, an invalid memory access that causes delivery of
SIGSEGV on
one CPU architecture may cause delivery of
SIGBUS on another
architecture, or vice versa.
For another example, using the x86
int instruction with a forbidden
argument (any number other than 3 or 128) causes delivery of
SIGSEGV,
even though
SIGILL would make more sense, because of how the CPU
reports the forbidden operation to the kernel.
kill(1),
clone(2),
getrlimit(2),
kill(2),
pidfd_send_signal(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),
swapcontext(3),
sysv_signal(3),
core(5),
proc(5),
nptl(7),
pthreads(7),
sigevent(7)
Русский
перевод
этой
страницы
руководства
был сделан
Alexander Golubev <
[email protected]>, Azamat Hackimov
<
[email protected]>, Hotellook, Nikita
<
[email protected]>, Spiros Georgaras <
[email protected]>, Vladislav
<
[email protected]>, Yuri Kozlov <
[email protected]>
и Иван
Павлов <
[email protected]>
Этот
перевод
является
бесплатной
документацией;
прочитайте
Стандартную
общественную
лицензию GNU
версии 3
или более
позднюю,
чтобы
узнать об
условиях
авторского
права. Мы не
несем
НИКАКОЙ
ОТВЕТСТВЕННОСТИ.
Если вы
обнаружите
ошибки в
переводе
этой
страницы
руководства,
пожалуйста,
отправьте
электронное
письмо на
[email protected]