Доступ процессов к файлам и каталогам
Сигналы
Чтобы завершить работу фонового процесса с помощью " ^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
Мефодий сначала запустил вечный цикл в качестве активного процесса, затем передал ему сигнал STOP с помощью " ^Z ", после чего дал команду bg ( b ack g round), запускающую в фоне последний остановленный процесс. Затем он снова перевел этот процесс в активный режим, и, наконец, убил его.
Передавать сигналы из командной строки можно любым процессам с помощью команды 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 -fH5.7. Запуск множества фоновых процессов
Мефодий решил запустить несколько процессов, а потом выборочно поубивать их. Для этого он, вдобавок к уже висящему в фоне sh loop, запустил в качестве активного процесса новый командный интерпретатор, sh (при этом изменилось приглашение командной строки ). Из этого sh он запустил в фоне еще один sh loop и новый bash loop. Сделал он это одной командной строкой (при этом команды разделяются символом " & ", т. е. "И"; выходит, что запускается и та, и другая команда). В ps он использовал новый ключ – " -H " (" H ierarchy", "иерархия"), который добавляет в выдачу 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 -fH5.8. Принудительное завершение процесса с помощью kill
Мефодий принялся убивать! Для начала он остановил работу давно запущенного 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 ps5.9. Завершение процесса естественным путем с помощью сигнала "Hang Up"
Ждать ему оставалось недолго. Этот sh завершился естественным путем, от команды exit, оставив после себя двух "детей-сирот" ( PID 3652 и 3653 ), которые тотчас же усыновил "отец всех процессов " – init ( PID 1 ). Когда Мефодий расправился и с ними – с помощью сигнала 1 ( HUP, то есть " H ang UP ", "повесить"2Имя этого сигнала происходит не от казни через повешение, а от повешенной телефонной трубки. ) – некому было даже сообщить об их кончине (если бы процесс-родитель был жив, на связанный с ним терминал вывелось бы что-нибудь вроде " [1]+ Hangup sh loop ").