Что такое сигналы и действия по умолчанию
Сигналы — прерывания для процессов
Аппаратное прерывание отвлекает процессор от текущей работы. Сигнал делает то же для процесса: асинхронно сообщает о событии и заставляет процесс отреагировать.
Сигнал — асинхронное уведомление процесса о событии. Каждый сигнал имеет номер и имя (SIGINT = 2). Процесс может реагировать действием по умолчанию, игнорировать сигнал или перехватить его своим обработчиком.
Жизненный цикл сигнала
- Генерация — ядро отмечает сигнал у процесса-получателя.
- Ожидание (pending) — сигнал сгенерирован, но ещё не доставлен.
- Доставка — ядро проверяет ожидающие сигналы, когда процесс возвращается из режима ядра в режим пользователя (после системного вызова, прерывания или при планировании), и выполняет действие.
Аналогия
Сигнал — записка, подсунутая под дверь. Генерация — записку подсунули. Ожидание — она лежит, пока хозяина нет дома или он сказал «не беспокоить» (блокировка). Доставка — хозяин заходит домой и читает её.
Основные сигналы
| № (x86 Linux) | Имя | Когда | По умолчанию |
|---|---|---|---|
| 1 | SIGHUP |
обрыв терминала, завершение лидера сеанса | Term |
| 2 | SIGINT |
Ctrl+C | Term |
| 3 | SIGQUIT |
Ctrl+\ | Core |
| 4 | SIGILL |
недопустимая инструкция | Core |
| 5 | SIGTRAP |
точка останова (отладчик) | Core |
| 6 | SIGABRT |
вызов abort() |
Core |
| 7 | SIGBUS |
ошибка шины / обращение за конец отображённого файла | Core |
| 8 | SIGFPE |
арифметическая ошибка (деление на ноль) | Core |
| 9 | SIGKILL |
безусловное уничтожение | Term |
| 10 | SIGUSR1 |
для программиста | Term |
| 11 | SIGSEGV |
недопустимое обращение к памяти | Core |
| 12 | SIGUSR2 |
для программиста | Term |
| 13 | SIGPIPE |
запись в канал, у которого нет читателей | Term |
| 14 | SIGALRM |
таймер alarm() |
Term |
| 15 | SIGTERM |
вежливая просьба завершиться (kill по умолчанию) |
Term |
| 17 | SIGCHLD |
потомок завершился или остановился | Ign |
| 18 | SIGCONT |
продолжить остановленный процесс | Cont |
| 19 | SIGSTOP |
безусловная остановка | Stop |
| 20 | SIGTSTP |
Ctrl+Z | Stop |
| 21 | SIGTTIN |
фоновый процесс читает терминал | Stop |
| 22 | SIGTTOU |
фоновый процесс пишет в терминал | Stop |
| 23 | SIGURG |
срочные данные в сокете | Ign |
| 28 | SIGWINCH |
изменился размер окна терминала | Ign |
| 34–64 | SIGRTMIN…SIGRTMAX |
сигналы реального времени | Term |
Номера отличаются на разных архитектурах — в программах всегда используйте имена. Список: kill -l, man 7 signal.
Действия по умолчанию
| Действие | Что происходит |
|---|---|
| Term | процесс завершается |
| Core | завершается и сохраняет образ памяти (core dump) для отладчика |
| Ign | сигнал отбрасывается |
| Stop | процесс останавливается (не завершается!) — состояние T |
| Cont | остановленный процесс продолжает работу; работающий — ничего не замечает |
Как запомнить
Ign по умолчанию — сигналы-«уведомления», которые никому не мешают: SIGCHLD, SIGURG, SIGWINCH. Stop — четыре сигнала остановки: SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU. Core — ошибки программы: SIGSEGV, SIGBUS, SIGFPE, SIGILL, SIGABRT, SIGQUIT, SIGTRAP.
Отправка сигналов
#include <signal.h>
kill(pid, SIGTERM); /* процессу pid */
kill(0, SIGINT); /* всем процессам своей группы (задача 8!) */
kill(-pgid, SIGHUP); /* всем процессам группы pgid */
kill(-1, SIGTERM); /* всем, кому можно (кроме init и себя) */
kill(pid, 0); /* только проверить существование и права */
raise(SIGABRT); /* себе */
Послать сигнал можно процессу того же пользователя; root — любому.
kill 4242 # SIGTERM
kill -9 4242 # SIGKILL
kill -STOP 4242 # остановить
kill -CONT 4242 # продолжить
kill -l # список сигналов
SIGTERM или SIGKILL
SIGTERM можно перехватить: программа сохранит данные и аккуратно завершится. SIGKILL нельзя ни перехватить, ни заблокировать, ни игнорировать — ядро уничтожит процесс сразу. Поэтому правильный порядок: сначала SIGTERM, и только если процесс не завершился — SIGKILL. Так же поступают init и systemd при выключении.
Итог
- Сигнал — асинхронное уведомление; этапы: генерация → ожидание → доставка → действие.
- Действия по умолчанию: Term, Core, Ign, Stop, Cont.
- Ign по умолчанию:
SIGCHLD,SIGURG,SIGWINCH; Stop:SIGSTOP,SIGTSTP,SIGTTIN,SIGTTOU. kill(pid, sig): pid > 0 — процессу, 0 — своей группе, < −1 — группе, −1 — всем.
Практика решено 0 из 6
Расставьте этапы жизни сигнала по порядку:
- Доставка: при возврате процесса из ядра в режим пользователя ядро проверяет ожидающие незаблокированные сигналы
- Ожидание (pending): сигнал отмечен, но ещё не доставлен (например, заблокирован или процесс не выполняется)
- Выполнение действия: по умолчанию, игнорирование или вызов обработчика
- Генерация: событие (ошибка, kill, терминал) — ядро отмечает сигнал в множестве ожидающих процесса
Каково действие по умолчанию для каждого сигнала?
| Завершить (Term) | Завершить + core dump (Core) | Игнорировать (Ign) | Остановить (Stop) | Продолжить (Cont) | |
|---|---|---|---|---|---|
| SIGINT | |||||
| SIGSEGV | |||||
| SIGCHLD | |||||
| SIGTSTP | |||||
| SIGCONT | |||||
| SIGKILL | |||||
| SIGABRT | |||||
| SIGUSR1 | |||||
| SIGTTIN | |||||
| SIGPIPE |
Какой номер у сигнала SIGKILL? (число)
Пошлите сигнал SIGTERM процессу с идентификатором pid и проверьте результат: при ошибке — perror("kill").
pid_t pid = 4242;
if (kill(pid, SIGTERM) == -1) {
perror("kill");
}
Кому будет послан сигнал при вызове kill(pid, sig)?
| Одному процессу pid | Всем процессам своей группы | Всем процессам группы |pid| | Всем процессам, которым можно послать | |
|---|---|---|---|---|
| pid > 0 | ||||
| pid == 0 | ||||
| pid < -1 | ||||
| pid == -1 |
Что делает kill(pid, 0)?
Войдите, чтобы отмечать пройденные уроки.