12.1.2. Простые сигналы

12.1.2. Простые сигналы

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

#include <signal.h>

void * signal(int signum, void *handler);

Здесь signum — это сигнал, который нужно обработать, a handler определяет действия, которое должно быть выполнено при доставке сигнала. Обычно handler — это указатель на функцию-обработчик сигнала, которая не принимает параметров и не возвращает значения. Когда сигнал доставлен процессу, ядро как можно скорее запускает функцию-обработчик. Когда функция возвращает управление, ядро возобновляет выполнение процесса с того места, где он был прерван. Системные инженеры распознают в этом механизме обработки сигналов аналог доставки аппаратных прерываний. Прерывания и сигналы очень похожи и у них возникают сходные проблемы.

Доступно множество номеров сигналов. В табл. 12.1 перечислены все сигналы, поддерживаемые в настоящее время Linux, за исключением сигналов реального времени. Они имеют символические имена, начинающиеся с SIG, и мы будем использовать SIGЧТО-ТО, говоря о каком-то из них.

Параметр handler может иметь два специальных значения — SIG_IGN и SIG_DFL (оба определены в <signal.h>). Если указано SIG_IGN, сигнал игнорируется, SIG_DFL сообщает ядру, что нужно выполнить действие по умолчанию, как правило, уничтожив процесс либо проигнорировав сигнал. Два сигнала — SIGKILL и SIGSTOP — не могут быть перехвачены. Ядро всегда выполняет действие по умолчанию для этих сигналов, соответственно, уничтожая процесс и приостанавливая его.

Функция signal() возвращает предыдущий обработчик сигнала (который мог быть SIG_IGN или SIG_DFL). Обработчики сигналов резервируются при создании новых процессов вызовом fork(), и все сигналы, которые установлены в SIG_IGN, игнорируются и после вызова exec()[53]. Все не игнорируемые сигналы после exec() устанавливаются в SIG_DFL.

Все это выглядит достаточно простым, пока вы не спросите себя: что произойдет, если сигнал SIGЧТО-ТО будет отправлен процессу, который уже исполняет обработчик сигнала для SIGЧТО-ТО.

Очевидно, что должно сделать ядро — так это прервать процесс и запустить обработчик сигнала сначала. Это порождает две проблемы. Первая — обработчик сигнала должен работать правильно, если он вызван тогда, когда уже сам работает. Хотя само по себе это и не сложно, но обработчики сигналов, которые манипулируют общепрограммными ресурсами, такими как глобальные структуры данных или файлы, должны быть написаны очень аккуратно. Функции, которые ведут себя правильно, когда вызваны подобным образом, называются реентерабельными функциями[54].

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

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

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

К сожалению, именно такая модель сигналов используется в ANSI/ISO-стандарте С[55]. Хотя программные интерфейсы надежных сигналов, в которых исправлен этот недостаток, уже широко распространены, стандартизация ненадежных сигналов в ANSI/ISO, видимо, останется навсегда.

Поделитесь на страничке

Следующая глава >

Похожие главы из других книг

7.2 СИГНАЛЫ

Из книги Архитектура операционной системы UNIX автора Бах Морис Дж

7.2 СИГНАЛЫ Сигналы сообщают процессам о возникновении асинхронных событий. Посылка сигналов производится процессами — друг другу, с помощью функции kill, — или ядром. В версии V (вторая редакция) системы UNIX существуют 19 различных сигналов, которые можно классифицировать


5.8.2. Сигналы

Из книги Linux-сервер своими руками автора Колисниченко Денис Николаевич

5.8.2. Сигналы Демон syslogd реагирует на следующие сигналы: SYGTERM, SIGINT, SIGQUIT, SIGHUP, SIGUSR1, SIGCHLD. Реакция демона на сигналы описана в табл. 5.8.Реакция демона на сигналы Таблица 5.8  Сигнал Реакция SIGTERM Завершает работу демона SIGINT, SIGQUIT Завершает работу демона, если выключена отладка


Простые классы

Из книги Microsoft Visual C++ и MFC. Программирование для Windows 95 и Windows NT автора Фролов Александр Вячеславович

Простые классы MFC содержит классы, соответствующие объектам типа простых геометрических фигур, текстовых строк и объектам, определяющим дату и время. В следующей таблице перечислены названия этих классов и их краткие описания. Класс Описание CPoint Объекты класса


6.6. Простые примеры

Из книги UNIX: взаимодействие процессов автора Стивенс Уильям Ричард

6.6. Простые примеры Поскольку очереди сообщений System V обладают живучестью ядра, мы можем написать несколько отдельных программ для работы с этими очередями и изучить их


10.5. Простые примеры

Из книги Программирование на языке Ruby [Идеология языка, теория и практика применения] автора Фултон Хэл

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


11.5. Простые программы

Из книги Программирование игр и головоломок автора Арсак Жак

11.5. Простые программы Поскольку семафоры System V обладают живучестью ядра, мы можем продемонстрировать работу с ними, написав несколько небольших программ, которые будут выполнять с семафорами различные действия. В промежутках между выполнением отдельных программ


13.4. Простые программы

Из книги QNX/UNIX [Анатомия параллелизма] автора Цилюрик Олег Иванович

13.4. Простые программы Приведем несколько примеров программ, работающих с разделяемой памятью


14.6. Простые программы

Из книги Операционная система UNIX автора Робачевский Андрей М.

14.6. Простые программы В этом разделе приведено несколько примеров простых программ, иллюстрирующих работу с разделяемой памятью System


5.14. Простые числа

Из книги Linux и UNIX: программирование в shell. Руководство разработчика. автора Тейнсли Дэвид


Простые числа

Из книги автора

Простые числа ??** Головоломка 16. Чемпион головоломок.На мой взгляд, наиболее замечательная арифметическая головоломка, над которой мне пришлось особенно долго работать и которая дала мне возможность получить некоторые удовлетворительные результаты, — это, конечно,


Сигналы

Из книги автора

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


18.3.1. Простые операторы if

Из книги автора

18.3.1. Простые операторы if Базовая структура оператора if выглядит следующим образом:if условие then командыfiПри использовании оператора if команды ветви then следует указывать в новой строке; если это правило нарушается, отображается сообщение об ошибке. По поводу применения


18.3.10. Простые операторы if else

Из книги автора

18.3.10. Простые операторы if else Следующая форма оператора if применяется чаще всего:if условие then команды1 elseкоманды2 fiЕсли условие не удовлетворяет тестированию, часть else оператора if позволяет перейти к соответствующей


26.2. Сигналы

Из книги автора

26.2. Сигналы Сигнал относится к типу сообщений, которые пересылаются из системы для информирования команды или сценария о совершении какого?либо события. Обычно речь идет об ошибках, связанных с функционированием памяти, о проблемах с доступом к информации или об