[Bovet & Cesati, 2005] и [Maxwell, 1999] раскрывают историю реализации сигналов в Linux. [Goodheart & Cox, 1994] приводят детальную информацию о реализации сигналов в ОС System V Release 4. Справочник GNU библиотеки C (доступен онлайн по адресу www.gnu.org) содержит обширное описание сигналов.

20.16. Упражнения

20.1. Как отмечается в разделе 20.3, функция sigaction() обладает большей переносимостью, чем signal(), если речь идет об установке обработчика сигнала. Замените signal() на sigaction() в программе из листинга 20.7 (sig_receiver.c).

20.2. Напишите программу, демонстрирующую следующее поведение: если установить диспозицию сигнала SIG_IGN, то программа никогда не перехватит (и вообще не заметит) этот сигнал.

20.3. Напишите программу, демонстрирующую действие флагов SA_RESETHAND и SA_NODEFER при установке обработчика сигнала с помощью функции sigaction().

20.4. Реализуйте использование функции siginterrupt() с помощью функции sigaction().

<p>21. Сигналы: обработчики сигналов</p>

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

1. Как спроектировать обработчик сигнала. Это вовлекает нас в дискуссию о реентерабельности и функциях, безопасных для асинхронных сигналов.

2. Альтернативы выполнению обычного возврата из обработчика сигнала, в частности применение для этих целей нелокального перехода goto.

3. Обработка сигналов в альтернативном стеке.

4. Использование флага SA_SIGINFO функции sigaction() для передачи обработчику сигнала возможности получить более детализированную информацию о сигнале, вызвавшем его активацию.

5. Как блокирующий системный вызов может быть прерван обработчиком сигнала и каким образом при необходимости данный системный вызов может быть перезапущен.

21.1. Проектирование обработчиков сигналов

Предпочтительнее писать простые обработчики сигналов. Одна из важных причин для этого — уменьшение вероятности создания состояний гонки. Чаще всего встречаются следующие две схемы обработчиков сигналов.

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

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

Дальше мы рассмотрим эти схемы, а также другие концепции, важные для проектирования обработчиков сигналов.

21.1.1. Сигналы не ставятся в очередь (еще раз о…)

В разделе 20.10 отмечалось, что доставка сигнала блокируется на время выполнения его обработчика (если не установлен флаг SA_NODEFER для функции sigaction()). Если сигнал (повторно) генерируется во время выполнения обработчика, то он помечается как ожидающий и доставляется по возвращении из обработчика. Еще отмечалось, что сигналы не ставятся в очередь. Если за время выполнения обработчика сигнал сгенерирован более одного раза, то он также помечается как ожидающий и будет позже доставлен только один раз.

Тот факт, что сигналы могут «исчезать», определенным образом влияет на проектирование обработчиков сигналов. Начать следует с того, что возможности точно подсчитать количество раз, когда сигнал был сгенерирован, нет. Более того, нам, возможно, потребуется создать код обработчика таким образом, чтобы у него была возможность отвечать на совершение сразу нескольких событий типа, соответствующего сигналу. Пример этого мы увидим при рассмотрении сигнала SIGCHLD в подразделе 26.3.1.

21.1.2. Реентерабельные функции и функции, безопасные для асинхронных сигналов

Не все системные вызовы и библиотечные функции могут быть безопасно вызваны из обработчика сигнала. Чтобы понять почему, необходимо объяснить две концепции: реентерабельные функции и функции, безопасные для асинхронных сигналов.

Реентерабельные и нереентерабельные функции

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

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