10.2. Действия сигналов
Каждый сигнал (вскоре мы представим полный список) имеет связанное с ним действие по умолчанию. POSIX обозначает это как диспозицию (disposition) сигнала. Это то действие, которое ядро осуществляет для процесса, когда поступает определенный сигнал. Действие по умолчанию варьирует:
Завершение
Процесс завершается.
Игнорирование
Сигнал игнорируется. Программа никогда не узнает, что что-то случилось.
Снимок образа процесса
Процесс завершается, и ядро создает файл core (в текущем каталоге процесса), содержащий образ работавшей на момент поступления сигнала программы. Снимок процесса может впоследствии использоваться с отладчиком для исследования состояния программы (см. главу 15 «Отладка»).
По умолчанию системы GNU/Linux создают файлы с именем
core.<i>pid</i>
, где
<i>pid</i>
является ID завершаемого процесса. (Это можно изменить; см.
sysctl(8).) Такое именование позволяет хранить в одном и том же каталоге несколько файлов
core
, за счет использования большего дискового пространства.
[105] Традиционные системы Unix называют файл
core
, и это ваше дело сохранить какие-нибудь файлы
core
для последующего изучения, если есть шанс создания других таких же файлов в том же каталоге.
Остановка
Процесс останавливается. Впоследствии он может быть возобновлен. (Если вы использовали управление заданиями оболочки с помощью CTRL-Z,
fg
и
bg
, вы понимаете остановку процесса.)
10.3. Стандартные сигналы С:
signal()
и raise()
Стандарт ISO С определяет первоначальный API управления сигналами V7 и новый API для посылки сигналов. Вы должны использовать их для программ, которым придется работать на не-POSIX системах, или в случаях, когда предоставляемые ISO С API возможности являются достаточными.
10.3.1. Функция
signal()
Действие сигнала изменяется с помощью функции
signal()
. Вы можете изменить действие на «игнорировать сигнал», «восстановить для сигнала действие системы по умолчанию» или «вызвать при появлении сигнала мою функцию с номером сигнала в качестве параметра».
Функция, которую вы предоставляете для распоряжения сигналом, называется обработчиком сигнала (или просто обработчиком), а установка ее в соответствующем месте осуществляет перехват (catch) сигнала.
Получив эти сведения, давайте перейдем к API. В заголовочном файле
<signal.h>
представлены определения макросов для поддерживаемых сигналов и объявления функций управления сигналами, предоставляемыми стандартом С:
#include <signal.h> /* ISO С */
void (*signal(int signum, void (*func)(int)))(int);
Это объявление для функции signal() почти невозможно прочесть. Поэтому справочная страница GNU/Linux signal(2) определяет ее таким способом:
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
Теперь это более вразумительно. Тип
sighandler_t
является указателем на функцию с возвращаемым типом
void
, которая принимает один целый аргумент. Это целое является номером поступающего сигнала.
Функция
signal()
принимает номер сигнала в качестве своего первого параметра, а указатель функции (новый обработчик) в качестве своего второго аргумента. Если последний не является указателем функции, он может быть лишь
SIG_DEF,
что означает «восстановить действие по умолчанию», либо
SIG_IGN
, что означает «игнорировать сигнал».
signal()
изменяет действие для
signum
и возвращает предыдущее действие. (Это дает вам возможность восстановить при желании предыдущее действие.) Возвращаемое значение может равняться также
SIG_ERR
, что указывает на произошедшую ошибку. (Некоторые сигналы невозможно перехватить или игнорировать; предоставление для них обработчика сигнала или неверный
signum
создают эту ошибку.) В табл. 10.1 перечислены сигналы, доступные под GNU/Linux, их числовые значения, действия по умолчанию для каждого, формальный стандарт или современная операционная система, которые их определяют, и смысл каждого.
Таблица 10.1. Сигналы GNU/Linux
Имя | Значение | По умолчанию | Источник | Смысл |
SIGHUP
| 1 | Term | POSIX | Отсоединение |
SIGINT
| 2 | Term | ISO C | Прерывание |
SIGQUIT
| 3 | Core | POSIX | Выход |
SIGILL
| 4 | Core | ISO C | Недействительная инструкция |
SIGTRAP
| 5 | Core | POSIX | Трассировочная ловушка |
SIGABRT
| 6 | Core | ISO C | Прекращение |
SIGIOT
| 6 | Core | BSD | Ловушка IOT |
SIGBUS
| 7 | Core | BSD | Ошибка шины |
SIGFPE
| 8 | Core | ISO C | Исключение с плавающей точкой |
SIGKILL
| 9 | Term | POSIX | Завершение, неблокируемый |
SIGUSR1
| 10 | Term | POSIX | Сигнал 1 пользователя |
SIGSEGV
| 11 | Core | ISO C | Нарушение сегмента |
SIGUSR2
| 12 | Term | POSIX | Сигнал 2 пользователя |
SIGPIPE
| 13 | Term | POSIX | Нарушенный канал |
SIGALRM
| 14 | Term | POSIX | Аварийные часы |
SIGTERM
| 15 | Term | ISO C | Завершение |
SIGSTKFLT
| 16 | Term | Linux | Ошибка стека в процессоре (не используется) |
SIGCHLD
| 17 | Ignr | POSIX | Изменение статуса порожденного процесса |
SIGCLD
| 17 | Ignr | System V | То же, что и SIGCHLD (для совместимости) |
SIGCONT
| 18 | | POSIX | Продолжить при остановке |
SIGSTOP
| 19 | Stop | POSIX | Стоп, неблокируемый |
SIGTSTP
| 20 | Stop | POSIX | Стоп от клавиатуры |
SIGTTIN
| 21 | Slop | POSIX | Фоновое чтение от tty |
SIGTTOU
| 22 | Stop | POSIX | Фоновая запись в tty |
SIGURG
| 23 | Ignr | BSD | Срочный сигнал сокета |
SIGXCPU
| 24 | Core | BSD | Превышение предела процессора |
SIGXFSZ
| 25 | Core | BSD | Превышение предела размера файла |
SIGVTALRM
| 26 | Term | BSD | Виртуальные аварийные часы |
SIGPROF
| 27 | Term | BSD | Профилирующие аварийные часы |
SIGWINCH
| 28 | Ignr | BSD | Изменение размера окна |
SIGIO
| 29 | Term | BSD | Возможен ввод/вывод |
SIGPOLL
| 29 | Term | System V | Опрашиваемое событие, то же, что и SIGIO (для совместимости) |
SIGPWR
| 30 | Term | System V | Повторный запуск из-за сбоя питания |
SIGSYS
| 31 | Core | POSIX | Неверный системный вызов |