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

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

Жанры

Linux программирование в примерах
Шрифт:

По получении сигнала ядро останавливает процесс, где бы он ни был. Затем оно имитирует вызов процедуры обработчика сигнала, передавая ему номер сигнала в качестве ее единственного аргумента. Ядро устраивает все таким образом, что нормальный возврат из функции обработчика сигнала (либо посредством

return
, либо в результате выпадения из конца функции) передает управление в ту точку программы, в которой она находилась в момент появления сигнала.

Что происходит после обработки сигнала, когда тот же самый сигнал появится в следующий раз снова? Остается ли обработчик на том же месте? Или же он сбрасывается, и для сигнала используется действие по умолчанию? Ответ, по историческим

причинам, «зависит от». В частности, стандарт С оставляет это на усмотрение реализации.

На практике V7 и традиционные системы System V, такие, как Solaris, устанавливают для сигнала действие по умолчанию.

Давайте рассмотрим простой обработчик сигнала в действии под Solaris. Следующая программа,

ch10-catchint.c
, перехватывает
SIGINT
. Обычно вы генерируете этот сигнал, набирая на клавиатуре CTRL-C.

1 /* ch10-catchint.c - перехват SIGINT, по крайней мере, однажды. */

2

3 #include <signal.h>

4 #include <string.h>

5 #include <unistd.h>

6

7 /* handler --- простой обработчик сигнала. */

8

9 void handler(int signum)

10 {

11 char buf[200], *cp;

12 int offset;

13

14 /* Пройти через это испытание , чтобы избежать fprintf. */

15 strcpy(buf, "handler: caught signal ");

16 cp = buf + strlen(buf); /* cp указывает на завершающий '\0' */

17 if (signum > 100) /* маловероятно */

18 offset = 3;

19 else if (signum > 10)

20 offset = 2;

21 else

22 offset = 1;

23 cp += offset;

24

25 *cp-- = '\0'; /* завершить строку */

26 while (signum >0) { /* work backwards, filling in digits */

27 *cp-- = (signum % 10) + '0';

28 signum /= 10;

29 }

30 strcat(buf, "\n");

31 (void)write(2, buf, strlen(buf));

32 }

33

34 /* main --- установить обработку сигнала и войти в бесконечный цикл */

35

36 int main(void)

37 {

38 (void)signal(SIGINT, handler);

39

40 for(;;)

41 pause; /* ждать сигнал, см. далее в главе */

42

43 return 0;

44 }

Строки 9–22 определяют функцию обработки сигнала (остроумно названную

handler
[106] ). Все, что эта
функция делает, — выводит номер перехваченного сигнала и возвращается. Для вывода этого сообщения она выполняет множество ручной работы, поскольку
fprintf
не является «безопасной» для вызова из обработчика сигнала. (Вскоре это будет описано в разделе 10.4.6 «Дополнительные предостережения».)

106

Handler (англ.) — обработчик — Примеч. перев.

Функция

main
устанавливает обработчик сигнала (строка 38), а затем входит в бесконечный цикл (строки 40–41). Вот что происходит при запуске:

$ ssh solaris.example.com

 /* Зарегистрироваться на доступной системе Solaris */

Last login: Fri Sep 19 04:33:25 2003 from 4.3.2.1.

Sun Microsystems Inc. SunOS 5.9 Generic May 2002

$ gcc ch10-catchint.c /* Откомпилировать программу */

$ a.out /* Запустить ее */

^C handler: caught signal 2 /* Набрать ^C, вызывается обработчик */

^C /* Попробовать снова, но на этот раз... */

$ /* Программа завершается */

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

void handler(int signum) {

 char buf[200], *cp;

 int offset;

 (void)signal(signum, handler); /* переустановить обработчик */

 /* ...оставшаяся часть функции как прежде... */

}

10.4.2. BSD и GNU/Linux

BSD 4.2 изменила способ работы

signal
. [107] На системах BSD обработчик сигнала после его возвращения остается на месте. Системы GNU/Linux следуют поведению BSD. Вот что происходит под GNU/Linux:

107

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

$ ch10-catchint /* Запустить программу */

handler: caught signal 2 /* Набираем ^C, вызывается обработчик */

handler: caught signal 2 /* И снова... */

handler: caught signal 2 /* И снова! */

handler: caught signal 2 /* Помогите! */

handler: caught signal 2 /* Как нам это остановить?! */

Quit (core dumped) /* ^\, генерирует SIGQUIT. Bay */

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

Неудержимый. Книга XXXVII

Боярский Андрей
37. Неудержимый
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Неудержимый. Книга XXXVII

Черный Маг Императора 5

Герда Александр
5. Черный маг императора
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Черный Маг Императора 5

Играть... в тебя

Зайцева Мария
3. Звериные повадки Симоновых
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Играть... в тебя

Черные ножи 2

Шенгальц Игорь Александрович
2. Черные ножи
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Черные ножи 2

Хорунжий

Вязовский Алексей
1. Индийский поход
Фантастика:
попаданцы
альтернативная история
5.40
рейтинг книги
Хорунжий

Печать Пожирателя 3

Соломенный Илья
3. Пожиратель
Фантастика:
городское фэнтези
аниме
сказочная фантастика
фэнтези
попаданцы
5.00
рейтинг книги
Печать Пожирателя 3

Сердце Дракона. нейросеть в мире боевых искусств (главы 1-650)

Клеванский Кирилл Сергеевич
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
7.51
рейтинг книги
Сердце Дракона. нейросеть в мире боевых искусств (главы 1-650)

Лихие. Депутат

Вязовский Алексей
4. Бригадир
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Лихие. Депутат

Я еще не барон

Дрейк Сириус
1. Дорогой барон!
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Я еще не барон

Технарь

Муравьёв Константин Николаевич
1. Технарь
Фантастика:
космическая фантастика
попаданцы
7.13
рейтинг книги
Технарь

Я все еще не царь. Книга XXVI

Дрейк Сириус
26. Дорогой барон!
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Я все еще не царь. Книга XXVI

Мастер 8

Чащин Валерий
8. Мастер
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Мастер 8

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

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

Воевода

Ланцов Михаил Алексеевич
5. Помещик
Фантастика:
альтернативная история
5.00
рейтинг книги
Воевода