b8c4c21f

Сигналы


Чтобы завершить работу фонового процесса с помощью "^C", Мефодию пришлось сначала сделать его активным. Это не всегда возможно и не всегда удобно. На самом деле, "^C" – это не волшебная кнопка-убийца, а предварительно установленный символ (с ascii-кодом 3), при получении которого с терминала Linux передаст активному процессу сигнал 2 (по имени INT, от "interrupt" – "прервать").

Сигнал – это способность процессов обмениваться стандартными короткими сообщениями непосредственно с помощью системы. Сообщение-сигнал не содержит никакой информации, кроме номера сигнала (для удобства вместо номера можно использовать предопределенное системой имя). Для того чтобы передать сигнал, процессу достаточно задействовать системный вызов kill(), а для того чтобы принять сигнал, не нужно ничего. Если процессу необходимо как-то по-особенному реагировать на сигнал, он может зарегистрировать обработчик, а если обработчика нет, за него отреагирует система. Как правило, это приводит к немедленному завершению процесса, получившего сигнал. Обработчик сигнала запускается асинхронно, немедленно после получения сигнала, что бы процесс в это время ни делал.

Сигнал - короткое сообщение, посылаемое системой или процессом другому процессу. Обрабатывается асинхронно специальной подпрограммой-обработчиком. Если процесс не обрабатывает сигнал самостоятельно, это делает система.

Два сигнала – 9 (KILL) и 19 (STOP) – всегда обрабатывает система. Первый из них нужен для того, чтобы убить процесс наверняка (отсюда и название). Сигнал STOP приостанавливает процесс: в таком состоянии процесс не удаляется из таблицы процессов, но и не выполняется до тех пор, пока не получит сигнал 18 (CONT) – после чего продолжит работу. В Linux сигнал STOP можно передать активному процессу с помощью управляющего символа "^Z":

[methody@localhost methody]$ sh loop ^Z [1]+ Stopped sh loop [methody@localhost methody]$ bg [1]+ sh loop & [methody@localhost methody]$ fg sh loop ^C [methody@localhost methody]$


Пример 5.6. Перевод процесса в фон с помощью "^Z" и bg (html, txt)

Мефодий сначала запустил вечный цикл в качестве активного процесса, затем передал ему сигнал STOP с помощью "^Z", после чего дал команду bg (back ground), запускающую в фоне последний остановленный процесс. Затем он снова перевел этот процесс в активный режим, и, наконец, убил его.

Передавать сигналы из командной строки можно любым процессам с помощью команды kill -сигнал PID или просто kill PID, которая передает сигнал 15 (TERM):

[methody@localhost methody]$ sh sh-2.05b$ sh loop & bash loop & [1] 3652 [2] 3653 sh-2.05b$ ps -fH UID PID PPID C STIME TTY TIME CMD methody 3590 1850 0 13:58 tty3 00:00:00 -bash methody 3634 3590 87 14:03 tty3 00:14:18 sh loop methody 3651 3590 0 14:19 tty3 00:00:00 sh methody 3652 3651 34 14:19 tty3 00:00:01 sh loop methody 3653 3651 35 14:19 tty3 00:00:01 bash loop methody 3654 3651 0 14:19 tty3 00:00:00 ps -fH

Пример 5.7. Запуск множества фоновых процессов (html, txt)

Мефодий решил запустить несколько процессов, а потом выборочно поубивать их. Для этого он, вдобавок к уже висящему в фоне sh loop, запустил в качестве активного процесса новый командный интерпретатор, sh (при этом изменилось приглашение командной строки). Из этого sh он запустил в фоне еще один sh loop и новый bash loop. Сделал он это одной командной строкой (при этом команды разделяются символом "&", т. е. "И"; выходит, что запускается и та, и другая команда). В ps он использовал новый ключ – "-H" ("Hierarchy", "иерархия"), который добавляет в выдачу ps отступы, показывающие отношения "родитель–потомок" между процессами:

sh-2.05b$ kill 3634 [1]+ Terminated sh loop sh-2.05b$ ps -fH UID PID PPID C STIME TTY TIME CMD methody 3590 1850 0 13:58 tty3 00:00:00 -bash methody 3651 3590 0 14:19 tty3 00:00:00 sh methody 3652 3651 34 14:19 tty3 00:01:10 sh loop methody 3653 3651 34 14:19 tty3 00:01:10 bash loop methody 3658 3651 0 14:23 tty3 00:00:00 ps -fH

Пример 5.8. Принудительное завершение процесса с помощью kill (html, txt)



Мефодий принялся убивать! Для начала он остановил работу давно запущенного sh, выполнявшего сценарий с вечным циклом (PID

3634). Как видно из предыдущего примера, этот процесс за 16 минут работы системы "съел" не менее 14 минут процессорного времени, и конечно, ничего полезного не сделал. Сигнал о том, что процесс-потомок "умер", дошел до обработчика в стартовом bash (PID

3590), и на терминал было выведено сообщение "[1]+ Terminated sh loop", после чего стартовый bash продолжил ждать завершения активного процесса – sh (PID

3651):

sh-2.05b$ exit [methody@localhost methody]$ ps -fH UID PID PPID C STIME TTY TIME CMD methody 3590 1850 0 15:17 tty3 00:00:00 -bash methody 3663 3590 0 15:23 tty3 00:00:00 ps -fH methody 3652 1 42 15:22 tty3 00:00:38 bash loop methody 3653 1 42 15:22 tty3 00:00:40 sh loop [methody@localhost methody]$ kill -HUP 3652 3653 [methody@localhost methody]$ ps PID TTY TIME CMD 3590 tty3 00:00:00 bash 3664 tty3 00:00:00 ps

Пример 5.9. Завершение процесса естественным путем с помощью сигнала "Hang Up" (html, txt)

Ждать ему оставалось недолго. Этот sh завершился естественным путем, от команды exit, оставив после себя двух "детей-сирот" (PID

3652 и 3653), которые тотчас же усыновил "отец всех процессов" – init (PID

1). Когда Мефодий расправился и с ними – с помощью сигнала 1 (HUP, то есть "Hang UP", "повесить"1)) – некому было даже сообщить об их кончине (если бы процесс-родитель был жив, на связанный с ним терминал вывелось бы что-нибудь вроде "[1]+ Hangup sh loop").


Содержание раздела