Сигналы и команда kill
Сигналы - это средство, с помощью которого процессам можно передать сообщения о некоторых событиях в системе. Сами процессы тоже могут генерировать сигналы, с помощью которых они передают определенные сообщения ядру и другим процессам. С помощью сигналов можно осуществлять такие акции управления процессами, как приостановка процесса, запуск приостановленного процесса, завершение работы процесса. Всего в Linux существует 63 разных сигнала, их перечень можно посмотреть по команде
[user]$ kill -l
Сигналы принято обозначать номерами или символическими именами. Все имена начинаются на SIG, но эту приставку иногда опускают: например, сигнал с номером 1 обозначают или как SIGHUP, или просто как HUP.
Когда процесс получает сигнал, то возможен один из двух вариантов развития событий. Если для данного сигнала определена подпрограмма обработки, то вызывается эта подпрограмма. В противном случае ядро выполняет от имени процесса действие, определенное по умолчанию для данного сигнала. Вызов подпрограммы обработки называется перехватом сигнала. Когда завершается выполнение подпрограммы обработки, процесс возобновляется с той точки, где был получен сигнал.
Можно заставить процесс игнорировать или блокировать некоторые сигналы. Игнорируемый сигнал просто отбрасывается процессом и не оказывает на него никакого влияния. Блокированный сигнал ставится в очередь на выдачу, но ядро не требует от процесса никаких действий до разблокирования сигнала. После разблокирования сигнала программа его обработки вызывается только один раз, даже если в течение периода блокировки данный сигнал поступал несколько раз.
В табл. 8.1. приведены некоторые из часто встречающихся сигналов.
1 | HUP | Hangup. Отбой | Да | Да | |
2 | INT | Interrupt. В случае выполнения простых команд вызывает прекращение выполнения, в интерактивных программах - прекращение активного процесса | Да | Да | <Ctrl>+<C> или <Del> |
3 | QUIT | Как правило, сильнее сигнала Interrupt | Да | Да | <Ctrl>+<\> |
4 | ILL | Illegal Instruction. Центральный процессор столкнулся с незнакомой командой (в большинстве случаев это означает, что допущена программная ошибка). Сигнал отправляется программе, в которой возникла проблема | Да | Да | |
8 | FPE | Floating Point Exception. Вычислительная ошибка, например, деление на ноль | Да | Да | |
9 | KILL | Всегда прекращает выполнение процесса | Нет | Нет | |
11 | SEGV | Segmentation Violation. Доступ к недозволенной области памяти | Да | Да | |
13 | PIPE | Была предпринята попытка передачи данных с помощью конвейера или очереди FIFO, однако не существует процесса, способного принять эти данные | Да | Да | |
15 | TERM | Software Termination. Требование закончить процесс (программное завершение) | Да | Да | |
17 | CHLD | Изменение статуса порожденного процесса | Да | Да | |
18 | CONT | Продолжение выполнения приостановленного процесса | Да | Да | |
19 | STOP | Приостановка выполнения процесса | Нет | Нет | |
20 | TSTR | Сигнал останова, генерируемый клавиатурой. Переводит процесс в фоновый режим | Да | Да | <Ctrl>+<Z> |
Как видите, некоторые сигналы можно сгенерировать с помощью определенных комбинаций клавиш. Но такие комбинации существуют не для всех сигналов. Зато имеется команда kill, которая позволяет послать заданному процессу любой сигнал. Как уже было сказано, с помощью этой команды можно получить список всех возможных сигналов, если указать опцию -l. Если после этой опции указать номер сигнала, то будет выдано его символическое имя, а если указать имя, то получим соответствующий номер.
Для посылки сигнала процессу (или группе процессов) можно воспользоваться командой kill в следующем формате:
[user]$ kill [-сигн] PID [PID..]
где сигн - это номер сигнала, причем если указание сигнала опущено, то посылается сигнал 15 (TERM - программное завершение процесса). Чаще всего используется сигнал 9 (KILL), с помощью которого суперпользователь может завершить любой процесс. Но сигнал этот очень "грубый", если можно так выразиться, поэтому его использование может привести к нарушению порядка в системе. Поэтому в большинстве случаев рекомендуется использовать сигналы TERM или QUIT, которые завершают процесс более "мягко".
Естественно, что наиболее часто команду kill вынужден применять суперпользователь. Он должен использовать ее для уничтожения процессов-зомби, зависших процессов (они показываются в листинге команды ps как <exiting>), процессов, которые занимают слишком много процессорного времени или слишком большой объем памяти и т. д. Особый случай - процессы, запущенные злоумышленником. Но обсуждение этого особого случая выходит за рамки данной книги.