Ю. Вахалия - UNIX изнутри (2003) (1114670), страница 35
Текст из файла (страница 35)
4.1. Обработка сигналов Сигналы вырабатываются вследствие происхождения асинхронных событий, которые могут произойти после любой инструкции в области кода процесса. После завершения обработки сигнала процесс восстанавливает свое функционирование с того места, где его выполнение было прервано сигналом (рис. 4.1). Если сигнал приходит тогда, когда процесс находится в стадии выполнения системного вызова, ядро системы прерывает обработку вызова и возвращает ошибку ЕТМТК. В ОС 4.2ВЯЭ был введен механизм автоматического рестарта системного вызова после сигнала (см. раздел 4.4.3). Система 4,3ВЯЭ предлагает вызов 119)лгегтврг, откл1оча1ощий эту возможность для конкретного сигнала.
4.2.2. Генерирование сигналов Ядро системы вырабатывает сигналы для процессов в ответ на различные события, причиной возникновения которых может быть сам процесс, получаю- 4.2. Генерирование и обработка сигналов 151 щий сигнал, другой процесс, а также прерывания или внешние действия. Основными источниками сигналов являются: + исключительные состояния (ехсерг)опз). После возникновения в процессе такого состояния (например, при попытке выполнения недопустимой инструкции) ядро системы уведомляет об этом процесс при по- моши сигнала; + другие процессы (огЬег ргосеззез).
Процесс может отправлять сигналы другому процессу или набору процессов при помощи системных вызовов ЙЙ1 или з1дзепд, Процесс может послать сигнал даже самому себе; + прерывания от терминала (гегпппа1 1пгеггиргз). При нажатии определенных комбинаций клавиш, например С1г1+С или СЫ+~ тегалаему (интерактивному) процессу терминала отправляется сигнал. Команда зггу позволяет пользователю назначать каждому сигналу, создаваемому терминалом, определенные клавиши; + управление заданиями ()оЬ сопсго1). Фоновые процессы, желающие произвести операции чтения или записи с терминалом, посылают сигналы управления заданиями.
Командные интерпретаторы, поддерживающие управление заданиями, такие как сзй или Йзй, используют сигналы для управления текущими и фоновыми процессами. Когда процесс завершается или приостанавливается, ядро системы уведомляет об этом его родителя посредством сигнала; + квоты (дпоГаз). Если процесс превысит отведенные ему лимиты использования процессора или допустимого размера файла, ядро пошлет такому процессу сигнал; + уведомления (по011саг)опз).
Процессу может потребоваться уведомление о возникновении определенных событий, например готовности устройства на ввод-вывод. Ядро информирует процесс о таких событиях при помощи сигнала; + будильники (а1агшз). Процесс может установить будильник на определенное время. Когда отведенное время истечет, ядро предупредит об этом процесс подачей сигнала тревоги.
Существуют три различных типа будильников, которые используют различные типы отсчетов, Так, отсчет 1Т1МЕЙ ЙЕАС приводит к измерению реального времени и вырабатыванию будильником сигнала 516АСЙМ. При указании 1Т1МЕЙ ЧТЙТОАС измеряется виртуальное время, то есть тот промежуток, когда процесс находился в режиме задачи,и подается сигнал 516НТАСЙМ. С 1Т1МЕЙ РЙОЕ ведется отсчет общего времени, используемого процессом как в режиме задачи, так и в режиме ядра, при этом генерируется сигнал 516РЙОЕ 162 глава 4.
Сигналы и управление сеансами Реализация будильников и отсчетов различается у разных производителей операционных систем. 4.2.3. Типичные примеры возникновения сигналов Разберем несколько примеров генерирования и доставки сигналов. Представьте, что пользователь нажимает комбинацию клавиш С1г1+С на своем терминале. Это действие приводит к возникновению прерывания терминала (точно так же, как и ввод любого иного символа с клавиатуры).
Драйвер терминала распознает комбинацию как символы, по вводу которых вырабатывается определенный сигнал, после чего отправляет созданный им сигнал 5161МТ текущему процессу данного терминала (если текущее задание состоит из более чем одного процесса, драйвер пошлет сигнал каждому его процессу). Когда этот процесс будет выбран планировщиком на выполнение, то он увидит сигнал, пытающийся вернуться в режим задачи после переключения контекста. Иногда интерактивный процесс уже является техуи~им во время возникновения прерывания.
В таком случае обработчик прерываний прервет его выполнение и отправит процессу сигнал'. После возврата из прерывания процесс осуществит проверку на наличие ожидающих сигналов и обнаружит этот сигнал. Однако исключительные состояния (или исключения) обычно приводят к возникновению синхронных сигналов. Причиной их часто являются ошибки в программе (например, попытка деления на ноль, недопустимые инструкции и т. д,), которые будут возникать в том же самом месте программы в случае, если она будет запущена с тождественными условиями (то есть если повторяется та же ветвь кода с теми же данными).
Когда в программе происходит исключение, оно является причиной возникновения ловушка в режиме ядра. Обработчик ловушки, находящийся внутри ядра, распознает исключительное состояние и отправляет соответствующий сигнал текущему процессу. Перед возвратом в режим задачи обработчик ловушки вызывает функцию Ьзгд() для получения процессом сигнала. Возможна ситуация, когда процесс одновременно ожидают несколько сигналов. В таком случае все сигналы будут обрабатываться по одному, Сигнал также может прийти в момент выполнения обработчика другого сигнала, что может стать причиной наложения обработчиков.
В большинстве реализаций систем НьПХ приложение имеет право запрашивать ядро о выборочной блокировке определенных сигналов перед запуском определенного обработчика (см. подробнее в разделе 4.4.3). Такой подход позволяет исключить или контролировать наложение обработчиков сигналов. ' На многопроцессорных системах процесс может оказаться функционируюпгим на другом процессоре. В таком случае обработчик должен создать специальное межпроцессорное прерывание для доставки сигнала его приемнику. 4.3. Ненадежные сигналы 153 4.2.4.
Спящие процессы и сигнзлы Что происходит в случае, если спящий процесс получит сигнал? Должен ли он быть разбужен для обработки этого сигнала или сигнал будет ожидать того момента, когда процесс выйдет из режима сна? Ответ на зти вопросы зависит от того, что стало причиной перехода процесса в режим сна. Если процесс спит в ожидании возникновения такого события, как завершение ввода-вывода с диска, то есть события, которое может наступить вскоре, имеет смысл немного подождать с доставкой сигналов. С другой стороны, если процесс ожидает ввода символа с клавиатуры, то такое ожидание может продолжаться очень долго.
Нам необходимо определиться, как прерывать такие процессы сигналами. Система Ич1Х поддерживает два вида сна: прерываемый и непрерываемый. Процесс, находящийся в состоянии сна до события, которое может произойти в ближайшее время (например, завершение дискового ввода-вывода), пребывает в непрерываемом сне и не может быть побеспокоен поступающими сигналами. Процесс, ожидающий такого события, как ввод-вывод терминала, который может не произойти в течение продолжительного времени, находится в прерываемом состоянии сна и будет разбужен посланным ему сигналом. Если сигнал предназначается для процесса, находящегося в непрерываемом сне, то такой сигнал будет помечен как ожидающий, и больше никаких действий со стороны этого сигнала по отношению к процессу происходить не будет.
Процесс не будет уведомлен о сипшле и после выхода из состояния сна до тех пор, пока он не окажется в состоянии возврата в режим задачи или не будет блокирован по прерываемому событию. Если процесс находится в состоянии, когда он будет заблокирован по прерываемому событию, то перед этой процедурой он проверит наличие сигналов. Если таковые будут найдены, процесс обработает их и прервет выполнение системного вызова.
Если сигнал будет создан уже после того, как процесс был блокирован, ядро системы разбудит такой процесс. Пробуждение и начало работы процесса может быть вызвано двумя причинами: либо произошло ожидаемое событие, либо его сон был прерван сигналом, поэтому в первую очередь процесс вызовет функцию !зз!дЦ и проверит, есть ли для него сигналы. В случае когда сигнал ожидает процесс, после вызова !зз!д() всегда происходит еще один вызов рз!д(), как это показано ниже: !г !1зз!9!)) Рю9(): 4.3. Ненадежные сигналы Изначальная реализация сигналов (в системах ЗЧК2 и более ранних версиях) была ненадежной и малоэффективной 12).
Эта реализация придерживается базовой модели, описанной в предыдущем разделе, и обладает рядом недостатков. 154 Глава 4. Сигналы и управление сеансами Наиболее важной проблемой является надежность доставки сигналов. Обработчики сигналов не являются постоянно установленными и не маскируют повторения одного и того же сигнала. Представьте, что программист установил обработчик на определенный сигнал.
После возникновения этого сигнала ядро системы сбросит действия, определенные для него, на установки по умолчанию перед тем, как вызовет обработчик. Программа, желающая обработать все повторные сигналы, должна каждый раз переустанавливать обработчик, как зто показано в листинге 4.1. Листинг 4.1. Переустановка обработчика сигналов чотб втдтпт Папб1ег (втд) тпс втд ° ( втдпа1 (5161МТ.
втдтпс Папб1ег), /* переустановка обработчика */ /* обработка сигнала*/ ) нато() ( втдпа1 (5161йТ, втдтпт Папб1ег); /* установка обработчика */ Однако этот подход приводит к состоянию состязательности. Представьте, что пользователь дважды быстро нажимает комбинацию клавиш Сгг1+С Первое нажатие влечет за собой возникновение сигнала 5161МТ, действие которого сбрасывается на принятое по умолчанию, после чего запустится обработчик. Если повторное нажатие произошло до переустановки обработчика, ядро системы выполнит действие по умолчанию и завершит процесс.