Чтение онлайн

на главную - закладки

Жанры

Основы программирования в Linux
Шрифт:

$ killall -HUP inetd

Программы могут обрабатывать сигналы с помощью библиотечной функции

signal
.

#include <signal.h>

void (*signal(int sig, void (*func)(int)))(int);

Это довольно сложное объявление говорит о том, что

signal
— это функция, принимающая два параметра,
sig
и
func
. Сигнал, который нужно перехватить или игнорировать, задается аргументом
sig
. Функция, которую следует вызвать при получении заданного сигнала, содержится в аргументе
func
. Эта функция должна принимать единственный аргумент типа
int
(принятый сигнал) и иметь тип
void
. Функция сигнала возвращает функцию того же типа, которая является предыдущим значением функции, заданной для обработки сигнала, или одно из двух специальных значений:

SIG_IGN
— игнорировать сигнал;

SIG_DFL
— восстановить поведение по умолчанию.

Пример сделает все понятным. В упражнении 11.7 вы напишете программу ctrlc.c, которая реагирует на нажатие комбинации клавиш <Ctrl>+<C> вместо обычного завершения выводом соответствующего сообщения. Повторное нажатие <Ctrl>+<C> завершает программу.

Упражнение 11.7. Обработка сигнала

Функция

ouch
реагирует на сигнал, передаваемый в параметре
sig
. Эта функция будет вызываться, когда возникнет сигнал. Она выводит сообщение и затем восстанавливает обработку сигнала по умолчанию для сигнала SIGINT (генерируется при нажатии комбинации клавиш <Ctrl>+<C>).

#include <signal.h>

#include <stdio.h>

#include <unistd.h>

void ouch(int sig) {

 printf("OUCH!
– I got signal %d\n", sig);

 (void)signal(SIGINT, SIG_DFL);

}

Функция

main
должна взаимодействовать с сигналом
SIGINT
, генерируемым при нажатии комбинации клавиш <Ctrl>+<C>. В остальное время она находится в бесконечном цикле, выводя один раз в секунду сообщение.

int main {

 (void)signal(SIGINT, ouch);

 while(1) {

printf("Hello World!\n");

sleep(1);

 }

}

Ввод комбинации клавиш <Ctrl>+<C> (отображается как

^C
в следующем далее выводе) в первый раз заставляет программу отреагировать и продолжиться. Когда вы нажимаете <Ctrl>+<C> снова, программа завершается, т.к. сигнал
SIGINT
вернул программе стандартное поведение, заставляющее ее завершиться.

$ ./ctrlcl

Hello World!

Hello World!

Hello World!

Hello World!

^C

OUCH!
– I got signal 2

Hello World!

Hello World!

Hello World!

Hello World!

^C

$

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

SIGINT
, которое в этой системе оказывается равным 2. Не стоит полагаться на стандартные числовые значения сигналов, в новых программах всегда пользуйтесь именами сигналов.

Примечание

Вызывать из обработчика сигнала все функции, например,

printf
, небезопасно. Удобный метод — использовать флаг, устанавливаемый в обработчике сигнала, и затем проверять этот флаг в функции
main
и выводить сообщение, если нужно. В конце этой главы вы найдете список вызовов, которые можно безопасно применять в теле обработчиков сигналов.

Как это работает

Программа устроена так, что, когда вы задаете сигнал

SIGINT
, нажимая комбинацию клавиш <Ctrl>+<C>, вызывает функцию
ouch
. После того как функция прерывания
ouch
завершится, программа продолжает выполняться, но восстанавливает реакцию на сигнал, принятую по умолчанию. (У разных версий UNIX, в особенности у потомков системы Berkeley UNIX, в течение многих лет сложилось разное поведение при получении сигналов. Если вы хотите восстановить поведение по умолчанию после возникновения сигнала, лучше всего запрограммировать его на конкретные действия.) Когда программа получает второй сигнал
SIGINT
, она выполняет стандартное действие, приводящее к завершению программы.

Если вы хотите сохранить обработчик сигнала и продолжать реагировать на комбинацию клавиш <Ctrl>+<C>, вам придется восстановить его, вызвав функцию

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

Примечание

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

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

Функция

signal
возвращает предыдущее значение обработчика для заданного типа сигнала, если таковой есть, или в противном случае
SIG_ERR
с установкой положительного значения в переменной
errno
. Если задан неверный сигнал или делается попытка обработать сигнал, который не может быть перехвачен или игнорироваться, например
SIGKILL
, переменной
errno
присваивается значение
EINVAL
.

Отправка сигналов

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

kill
. Вызов завершится аварийно, если у программы нет полномочий на отправку сигнала, часто потому что процесс-получатель принадлежит другому пользователю. Эта функция эквивалентна команде оболочки с тем же именем.

#include <sys/types.h>

#include <signal.h>

int kill(pid_t pid, int sig);

Функция

kill
посылает заданный сигнал
sig
процессу с идентификатором, заданным в аргументе
pid
. В случае успеха она возвращает 0. Для отправки сигнала посылающий процесс должен иметь право на выполнение этого действия. Обычно это означает, что у обоих процессов должен быть один и тот же идентификатор пользователя ID (т.е. вы можете отправить сигнал только одному из собственных процессов, хотя суперпользователь может отправлять сигналы любому процессу).

Поделиться:
Популярные книги

Анна Иоановна

Сахаров Андрей Николаевич
9. Романовы. Династия в романах
Проза:
историческая проза
5.60
рейтинг книги
Анна Иоановна

Локки 6. Потомок бога

Решетов Евгений Валерьевич
6. Локки
Фантастика:
аниме
фэнтези
5.00
рейтинг книги
Локки 6. Потомок бога

Академия

Сай Ярослав
2. Медорфенов
Фантастика:
юмористическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Академия

Язык программирования Си. Издание 3-е, исправленное

Ритчи Деннис М.
Компьютеры и Интернет:
программирование
5.00
рейтинг книги
Язык программирования Си. Издание 3-е, исправленное

Бастард Императора. Том 15

Орлов Андрей Юрьевич
15. Бастард Императора
Фантастика:
городское фэнтези
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Бастард Императора. Том 15

Инженер Петра Великого 2

Гросов Виктор
2. Инженер Петра Великого
Фантастика:
попаданцы
альтернативная история
фэнтези
5.00
рейтинг книги
Инженер Петра Великого 2

Стеллар. Компиляция. Книги 1-9

Прокофьев Роман Юрьевич
Стеллар
Фантастика:
киберпанк
рпг
постапокалипсис
технофэнтези
5.00
рейтинг книги
Стеллар. Компиляция. Книги 1-9

Шакалы

Леонов Николай Иванович
18. Гуров
Детективы:
полицейские детективы
7.36
рейтинг книги
Шакалы

Княжий пир

Никитин Юрий Александрович
1. Княжеский пир
Фантастика:
фэнтези
7.17
рейтинг книги
Княжий пир

Львы Эльдорадо (сборник)

Карсак Франсис
Библиотека приключений
Фантастика:
научная фантастика
8.12
рейтинг книги
Львы Эльдорадо (сборник)

Изменяющий-Механик. Компиляция. Книги 1-18

Усманов Хайдарали
Собрание сочинений
Фантастика:
боевая фантастика
космическая фантастика
5.00
рейтинг книги
Изменяющий-Механик. Компиляция. Книги 1-18

Укрощая хаос

Гэлли Бен
3. Гонка за смертью
Фантастика:
фэнтези
готический роман
5.00
рейтинг книги
Укрощая хаос

Неучтенный элемент. Том 8

NikL
8. Антимаг. Вне системы
Фантастика:
фэнтези
5.00
рейтинг книги
Неучтенный элемент. Том 8

Изгнание

Фейхтвангер Лион
Проза:
проза прочее
6.25
рейтинг книги
Изгнание