• каким образом процесс отвечает на сигнал по умолчанию, а также средства, с помощью которых процессы могут изменять свой ответ на сигнал, в частности, за счет использования обработчика сигнала — программно-определенной функции, активируемой автоматически в случае получения сигнала;

• использование сигнальной маски процесса для блокировки сигналов, а также связанного с ней понятия ожидающих сигналов;

• как процесс может приостановить выполнение и подождать доставки сигнала.

20.1. Концепции и общие сведения

Сигнал — это оповещение процесса о том, что произошло некое событие. Иногда сигналы также описываются как программные прерывания. Сигналы аналогичны аппаратным прерываниям в том смысле, что они останавливают нормальное выполнение программы. В большинстве случаев невозможно предсказать, когда именно будет доставлен тот или иной сигнал.

Один процесс может (при наличии необходимых разрешений) отправить сигнал другому процессу. При таком использовании сигналы могут рассматриваться как технология синхронизации либо даже как примитивная форма межпроцессного взаимодействия (IPC). Процесс также может отправить сигнал самому себе. Однако обычно источником большинства сигналов, отправляемых в процесс, является ядро. Далее перечислены несколько типов событий, свершение которых заставляет ядро сгенерировать сигнал для процесса.

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

• Пользователь ввел один из специальных символов терминала, генерирующих сигналы. Примерами таких символов могут быть символ прерывания (обычно Ctrl+C) и символ приостановки (обычно Ctrl+Z).

• Произошло программное событие. Например, появился ввод из файлового дескриптора, размер окна терминала был изменен, сработал таймер, для процесса было превышено временное ограничение ЦП либо был завершен дочерний процесс данного процесса.

Каждому сигналу присваивается уникальный идентификатор — (небольшое) целое число, нумерация задается последовательно по возрастанию, начиная с 1. Эти целые числа определены в файле с символьными именами в формате SIGxxxx. Поскольку числа для каждого из сигналов отличаются в зависимости от реализации, в программах всегда применяются символьные имена. Например, когда пользователь вводит символ прерывания, процессу доставляется сигнал SIGINT (с номером 2).

Сигналы можно разделить на две большие категории. Первый набор сигналов состоит из традиционных, или стандартных, сигналов, которые используются ядром для оповещения процессов о свершении событий. В Linux стандартные сигналы пронумерованы от 1 до 31. Мы опишем их в этой главе. Второй набор состоит из сигналов реального времени, отличия которых от стандартных описаны в разделе 22.8.

Говорят, что сигнал генерируется каким-либо событием. После генерации происходит доставка в процесс, который затем выполняет определенные действия для ответа на полученный сигнал. После того, как сигнал был сгенерирован, и до его доставки, говорят, что сигнал находится в состоянии ожидания.

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

• Сигнал игнорируется, то есть сбрасывается ядром и не влияет на процесс. (Процесс никогда даже не узнает о том, что данный сигнал был отправлен.)

Процесс завершается. Иногда это называют аварийным завершением процесса, что противопоставляется нормальному завершению — при использовании функции exit().

Перейти на страницу:

Похожие книги