Выбрать главу

Для отправления сигнала служит команда kill(1):

kill sig_no pid

где sig_nо — номер или символическое название сигнала, a pid — идентификатор процесса, которому посылается сигнал. Администратор системы может посылать сигналы любым процессам, обычный же пользователь может посылать сигналы только процессам, владельцем которых он является (реальный и эффективный идентификаторы процесса должны совпадать с идентификатором пользователя[10]). Например, чтобы послать процессу, который вы только что запустили в фоновом режиме, сигнал завершения выполнения SIGTERM, можно воспользоваться командой:

$ long_program &

Запустим программу в фоновом режиме

$ kill $!

По умолчанию команда kill(1) посылает сигнал SIGTERM; переменная $! содержит PID последнего процесса, запущенного в фоновом режиме

При получении сигнала процесс имеет три варианта действий для выбора:

1. Он может игнорировать сигнал. Не следует игнорировать сигналы, вызванные аппаратной частью, например, при делении на 0 или ссылке на недопустимые области памяти, так как дальнейшие результаты в отношении данного процесса непредсказуемы.

2. Процесс может потребовать действия по умолчанию. Как ни печально, обычно это сводится к завершению выполнения процесса.

3. Наконец, процесс может перехватить сигнал и самостоятельно обработать его. Например, перехват сигнала SIGINT позволит процессу удалить созданные им временные файлы, короче, достойно подготовиться к "смерти". Следует иметь в виду, что сигналы SIGKILL и SIGSTOP нельзя ни перехватить, ни игнорировать.

По умолчанию команда kill(1) посылает сигнал с номером 15 — SIGTERM[11], действие по умолчанию для которого — завершение выполнения процесса, получившего сигнал.

Иногда процесс продолжает существовать и после отправления сигнала SIGTERM. В этом случае можно применить более жесткое средство — послать процессу сигнал SIGKILL с номером (9), — поскольку этот сигнал нельзя ни перехватить, ни игнорировать:

$ kill -9 pid

Однако возможны ситуации, когда процесс не исчезает и в этом случае. Это может произойти для следующих процессов:

□ Процессы-зомби. Фактически процесса как такового не существует, осталась лишь запись в системной таблице процессов, поэтому удалить его можно только перезапуском операционной системы. Зомби в небольших количествах не представляют опасности, однако если их много, это может привести к переполнению таблицы процессов.

□ Процессы, ожидающие недоступные ресурсы NFS (Network File System), например, записывающие данные в файл файловой системы удаленного компьютера, отключившегося от сети. Эту ситуацию можно преодолеть, послав процессу сигнал SIGINT или SIGQUIT.

□ Процессы, ожидающие завершения операции с устройством, например, перемотки магнитной ленты.

Сигналы могут не только использоваться для завершения выполнения но и иметь специфическое для приложения (обычно для системных демонов) значение (естественно, это не относится к сигналам SIGKILL и SIGSTOP). Например, отправление сигнала SIGHUP серверу имен DNS named(1M) вызовет считывание базы данных с диска. Для других приложений могут быть определены другие сигналы и соответствующие им значения.

Более подробно сигналы мы рассмотрим в главах 2 и 3.

Устройства

Как уже отмечалось, UNIX "изолирует" приложения (а значит и пользователя) от аппаратной части вычислительной системы. Например, в имени файла отсутствует указатель диска, на котором этот файл расположен, а большая часть взаимодействия с периферийными устройствами неотличима от операций с обычными файлами.

UNIX предоставляет единый интерфейс различных устройств системы в виде специальных файлов устройств. Специальный файл устройства связывает прикладное приложение с драйвером устройства. Каждый специальный файл соответствует какому-либо физическому устройству (например, диску, накопителю на магнитной ленте, принтеру или терминалу) или т.н. псевдоустройству (например, сетевому интерфейсу, пустому устройству, сокету или памяти). Вся работа приложения с устройством происходит через специальный файл, а соответствующий ему драйвер обеспечивает выполнение операций ввода/вывода в соответствии с конкретным протоколом обмена данными с устройством.

Существует два типа специальных файлов устройств:

□ Файлы блочных устройств

□ Файлы символьных устройств

Файлы блочных устройств

Файлы блочных устройств служат интерфейсом к устройствам, обмен данными с которыми происходит большими фрагментами, называемыми блоками. При этом ядро операционной системы обеспечивает необходимую буферизацию. Примером физических устройств, соответствующих этому типу файлов, являются жесткие диски. Приведем фрагмент подробного списка файлов каталога /dev системы Digital UNIX, отражающий файлы для доступа к первому и второму разделам первого диска SCSI:

brw------- 1 root system 8, 1 Apr 18 11:03 /dev/rz0a

brw------- 1 root system 8, 1 Apr 18 13:15 /dev/rz0b

Файлы символьных устройств

Файлы символьных устройств используются для доступа к устройствам, драйверы которых обеспечивают собственную буферизацию и побайтную передачу данных. В качестве примера устройств с символьным интерфейсом можно привести терминалы, принтеры и накопители на магнитной ленте. Заметим, что одно и то же физическое устройство может иметь как блочный, так и символьный интерфейсы. Для блочных устройств такой интерфейс также называют интерфейсом доступа низкого уровня (raw interface). Так, для побайтного доступа к разделам диска, приведенным в предыдущем примере, используются соответствующие файлы:

crw------- 1 root system   8, 1 Apr 18 11:04 /dev/rrz0a

crw------- 1 root system   8, 1 Apr 18 13:15 /dev/rrz0b

crw-r----- 1 root system   13,1 Apr 18 18:08 /dev/kmem

crw-rw-rw- 1 root system   7, 0 Apr 18 15:30 /dev/ptyp0

crw-rw-rw- 1 root system   7, 1 Apr 18 15:20 /dev/ptyp1

crw-rw-rw- 1 bill terminal 3, 2 Apr 18 16:10 /dev/tty02

crw-rw-rw- 1 bin  terminal 3, 3 Apr 18 16:10 /dev/tty03

Последние три строки списка представляют интерфейс доступа к виртуальной памяти ядра и двум псевдотерминалам.

В поле размера файла (пятая колонка вывода команды ls(1)) у специальных файлов устройств выводятся два числа. Это так называемые старшее (major) и младшее (minor) числа. Часто драйвер обслуживает более одного устройства. При этом старшее число указывает ядру на конкретный драйвер (например, драйвер псевдо-терминалов), а младшее передается драйверу и указывает на конкретное устройство (например, конкретный псевдотерминал).

Интерфейс файловой системы для взаимодействия с устройством схематически представлен на рис. 1.7.

вернуться

10

Точнее, с реальным и эффективным идентификаторами процесса, посылающего сигнал. Если вы посылаете сигнал командой kill(1), работая в shell, то речь идет о командном интерпретаторе.

вернуться

11

Соответствие между символьными именами и номерами сигналов может отличаться различных версиях UNIX. Команда kill -l выводит номера сигналов и их имена.