Здавалка
Главная | Обратная связь

Kill(getpid(), sig)



Сигналы.

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

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

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

 

Генерация сигналов

События, которые генерируют сигналы, делятся на три основные группы: ошибки, внешние события и явные запросы.

Ошибка означает, что программа сделала что-то недопустимое и не может продолжить своё выполнение. Не все типы ошибок генерируют сигналы (на самом деле, большинство ошибок не генерирует). Например, попытка открытия несуществующего файла — ошибка, но она не генерирует сигнал, вместо этого системный вызов open возвращает -1. Вообще ошибки, которые связаны с библиотечными функциями и системными вызовами, сообщаются программе с помощью специальных возвращаемых значений. Ошибки, которые могу встретиться в любом месте программы, а не только в библиотечных функциях и системны вызовах генерируют сигналы. К таким ошибкам относятся деление на 0 и неверное обращние к памяти.

Внешнее событие обычно относится к операциям ввода/вывода или другим процессам. Например, получение данных при асинхронных операциях, срабатывание таймера, завершение дочернего процесса.

Явный запрос предполагает использование функций (kill) задача которых — сгенерировать сигнал.

Сигналы могут генерироваться синхронно или асинхронно. Синхронный сигнал относится к некоторому действию в программе и доставляется (если только не заблокирован) во время этого действия. Большинство ошибок генерируют синхронные сигналы. Посылка процессом сигнала самому себе также синхронна.

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

Каждый тип сигнала как правило синхронен или асинхронен. Например, сигналы, соответствующие ошибкам выполнения программы, синхронны. Но любой сигнал может быть синхронным или асинхронным, когда посылается явно.

Системный вызов kill позволяет послать сигнал процессу или группе процессов.

int kill(pid_t pid, int sig);

Если pid больше нуля, заданный сигнал sig посылается процессу с заданным идентификатором процесса.

Если pid равен 0, сигнал sig посылается всем процессам в группе процессов, к которой относится данный процесс.

Если pid меньше -1, сигнал sig посылается всем процессам в группе процессов с идентификатором pid.

Наконец, если pid равен -1, сигнал sig посылается всем процессам с тем же эффективным идентификатором пользователя, что у текущего процесса.

Если номер сигнала равен 0, сигнал не посылается, но все возможные ошибки проверяются. Таким образом можно проверить, например, существование процесса с заданным pid.

Процесс может послать сигнал самому себе с помощью вызова вида

kill(getpid(), sig)

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

В случае успеха системный вызов возвращает 0. Если сигнал посылается группе процессов, вызов kill заканчивается успешно, если сигнал был послан хотя бы одному процессу в группе. Нет способа узнать, какой из процессов получил сигнал, или получили ли его они все. В случае неудачи системный вызов возвращает значение -1, а переменная errno устанавливается в код ошибки, который может быть одним из следующих:

EINVAL - Аргумент sig является недопустимым или неподдерживаемым номером сигналом.

EPERM - Недостаточно прав послать сигнал процессу или группе процессов.

ESCRH - Аргумент pid не является правильным номером процесса или группы процессов. Действие функции raise, определённой следующим образом:

int raise(int sig);

эквивалентно вызову kill(getpid(), sig) .

 

Получение сигналов

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

Доставка сигнала означает выполнение определённого действия. Для некоторых сигналов (SIGKILL и SIGSTOP) это действие фиксировано, но для большинства сигналов у программы есть выбор: игнорировать сигнал, обрабатывать сигнал или выполнять действие по умолчанию для данного сигнала. Программа может задавать реакцию на сигнал с помощь вызовов signal или sigaction. Во время работы обработчика сигнала этот тип сигнала заблокирован.

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

Если процесс получает сигнал, который ни обрабатывается, ни игнорируется, выполняется действие по умолчанию. Каждый тип сигналов имеет своё действие по умолчанию. Для большинства сигналов действием по умолчанию является завершение процесса. Для некоторых сигналов, обозначающих «безобидные» события, действие по умолчанию состоит в том чтобы ничего не делать. Обратите внимание, что такое действие по умолчанию не является игнорированием сигнала.

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

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

Дамп памяти имеет по умолчанию имя core и создаётся в текущем каталоге. Ядро записывает дамп памяти в случае, когда выполняется хотя бы одно из следующих условий:

- Эффективный идентификатор пользователя или группы пользователей процесса не совпадает с реальным идентификатором пользователя или группы пользователей.

- У процесса отсутствуют права записи в текущий каталог процесса, если файл core не существует.

- У процесса отсутствуют права записи в файл core в текущем каталоге, если такой файл существует.

- Пользователь запретил создание файла дампа памяти с помощью команды ulimit -c 0.

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

 







©2015 arhivinfo.ru Все права принадлежат авторам размещенных материалов.