Системный вызов signal(). Установка собственного обработчика сигнала
Одним из способов изменения поведения процесса при получении сигнала в операционной системе UNIX является использование системного вызова signal().
Системный вызов signal() Прототип системного вызова #include <signal.h> void (*signal (int sig, void (*handler) (int)))(int); Описание системного вызова Системный вызов signal служит для изменения реакции процесса на какой-либо сигнал. Хотя прототип системного вызова выглядит довольно пугающе, ничего страшного в нем нет. Приведенное выше описание можно словесно изложить следующим образом: функция signal, возвращающая указатель на функцию с одним параметром типа int, которая ничего не возвращает, и имеющая два параметра: параметр sig типа int и параметр handler, служащий указателем на ничего не возвращающую функцию с одним параметром типа int. Параметр sig – это номер сигнала, обработку которого предстоит изменить. Параметр handler описывает новый способ обработки сигнала – это может быть указатель на пользовательскую функцию – обработчик сигнала, специальное значение SIG_DFL или специальное значение SIG_IGN. Специальное значение SIG_IGN используется для того, чтобы процесс игнорировал поступившие сигналы с номером sig, специальное значение SIG_DFL – для восстановления реакции процесса на этот сигнал по умолчанию. Возвращаемое значение Системный вызов возвращает указатель на старый способ обработки сигнала, значение которого можно использовать для восстановления старого способа в случае необходимости. |
Этот системный вызов имеет два параметра: один из них задает номер сигнала, реакцию процесса на который требуется изменить, а второй определяет, как именно мы собираемся ее менять. Для первого варианта реакции процесса на сигнал (см. раздел "Понятие сигнала. Способы возникновения сигналов и виды их обработки") – его игнорирования – применяется специальное значение этого параметра SIG_IGN. Например, если требуется игнорировать сигнал SIGINT, начиная с некоторого места работы программы, в этом месте программы мы должны употребить конструкцию
(void) signal(SIGINT, SIG_IGN);
Для второго варианта реакции процесса на сигнал – восстановления его обработки по умолчанию – применяется специальное значение этого параметра SIG_DFL. Для третьего варианта реакции процесса на сигнал в качестве значения параметра подставляется указатель на пользовательскую функцию обработки сигнала, которая должна иметь прототип вида
void *handler(int);
Ниже приведен пример скелета конструкции для пользовательской обработки сигнала SIGHUP.
void *my_handler(int nsig) { <обработка сигнала> } int main() { ... (void)signal(SIGHUP, my_handler); ... }
В качестве значения параметра в пользовательскую функцию обработки сигнала (в нашем скелете – параметр nsig) передается номер возникшего сигнала, так что одна и та же функция может быть использована для обработки нескольких сигналов.