Доставка и обработка сигнала
Доставка и обработка сигнала
Для каждого сигнала в системе определена обработка по умолчанию, которую выполняет ядро, если процесс не указал другого действия. В общем случае существуют пять возможных действий: завершить выполнение процесса (с созданием образа core и без), игнорировать сигнал, остановить процесс и продолжить процесс (справедливо для остановленного процесса, для остальных сигнал игнорируется), наиболее употребительным из которых является первое.
Как уже обсуждалось в главе 2, процесс может изменить действие по умолчанию, либо зарегистрировав собственный обработчик сигнала, либо указав, что сигнал следует игнорировать. Процесс также может заблокировать сигнал, отложив на некоторое время его обработку. Это возможно не для всех сигналов. Например, для сигналов SIGKILL и SIGSTOP единственным действием является действие по умолчанию, эти сигналы нельзя ни перехватить, ни заблокировать, ни игнорировать. Для ряда сигналов, преимущественно связанных с аппаратными ошибками и особыми ситуациями, обработка, отличная от умалчиваемой, не рекомендуется, так как может привести к непредсказуемым (для процесса) результатам.
Следует заметить, что любая обработка сигнала, в том числе обработка по умолчанию, подразумевает, что процесс выполняется. На системах с высокой загрузкой это может привести к существенным задержкам между отправлением и доставкой сигнала, т.к. процесс не получит сигнал, пока не будет выбран планировщиком, и ему не будут предоставлены вычислительные ресурсы. Этот вопрос был затронут при разговоре о точности таймеров, которые может использовать процесс.
Доставка сигнала происходит после того, как ядро от имени процесса вызывает системную процедуру issig(), которая проверяет, существуют ли ожидающие доставки сигналы, адресованные данному процессу. Функция issig() вызывается ядром в трех случаях:
1. Непосредственно перед возвращением из режима ядра в режим задачи после обработки системного вызова или прерывания.
2. Непосредственно перед переходом процесса в состояние сна с приоритетом, допускающим прерывание сигналом.
3. Сразу же после пробуждения после сна с приоритетом, допускающим прерывание сигналом.
Если процедура issig() обнаруживает ожидающие доставки сигналы, ядро вызывает функцию доставки сигнала, которая выполняет действия по умолчанию или вызывает специальную функцию sendsig(), запускающую обработчик сигнала, зарегистрированный процессом. Функция sendsig() возвращает процесс в режим задачи, передает управление обработчику сигнала, а затем восстанавливает контекст процесса для продолжения прерванного сигналом выполнения.
Рассмотрим типичные ситуации, связанные с отправлением и доставкой сигналов. Допустим, пользователь, работая за терминалом, нажимает клавишу прерывания (<Del> или <Ctrl>+<C> для большинства систем). Нажатие любой клавиши вызывает аппаратное прерывание (например, прерывание от последовательного порта), а драйвер терминала при обработке этого прерывания определяет, что была нажата специальная клавиша, генерирующая сигнал, и отправляет текущему процессу, связанному с терминалом, сигнал SIGINT. Когда процесс будет выбран планировщиком и запущен на выполнение, при переходе в режим задачи он обнаружит поступление сигнала и обработает его. Если же в момент генерации сигнала терминальным драйвером процесс, которому был адресован сигнал, уже выполнялся (т.е. был прерван обработчиком терминального прерывания), он также обработает сигнал при возврате в режим задачи после обработки прерывания.
Работа с сигналами, связанными с особыми ситуациями, незначительно отличается от вышеописанной. Особая ситуация возникает при выполнении процессом определенной инструкции, вызывающей в системе ошибку (например, деление на ноль, обращение к недопустимой области памяти, недопустимая инструкция или вызов и т.д.). Если такое происходит, вызывается системный обработчик особой ситуации, и процесс переходит в режим ядра, почти так же, как и при обработке любого другого прерывания. Обработчик отправляет процессу соответствующий сигнал, который доставляется, когда выполнение возвращается в режим задачи.
При обсуждении состояния сна процесса мы выделили две категории событий, вызывающих состояние сна процесса: допускающие прерывание сигналом и не допускающие такого прерывания. В последнем случае сигнал будет терпеливо ожидать нормального пробуждения процесса, например, после завершения операции дискового ввода/вывода.
В первом случае, доставка сигнала будет проверена ядром непосредственно перед переходом процесса в состояние сна. Если такой сигнал поступил, будет вызван обработчик сигнала, а системный вызов, который выполнялся процессом, будет аварийно завершен с ошибкой EINTR. Если генерация сигнала произошла в течение сна процесса, ядро будет вынуждено разбудить его и снять прерванный системный вызов (ошибка EINTR). После пробуждения процесса либо вследствие получения сигнала, либо из-за наступления ожидаемого события, ядром будет вызвана функция issig(), которая обнаружит поступление сигнала и вызовет соответствующую обработку.[41]
Данный текст является ознакомительным фрагментом.