Вход/Регистрация
UNIX: разработка сетевых приложений
вернуться

Стивенс Уильям Ричард

Шрифт:

3. Мы можем установить действие для сигнала по умолчанию, задав его как

SIG_DFL
. Действие сигнала по умолчанию обычно заключается в завершении процесса по получении сигнала, а некоторые сигналы генерируют копию области памяти процесса в его текущем каталоге (так называемый дамп— core dump). Есть несколько сигналов, для которых действием по умолчанию является игнорирование. Например,
SIGCHLD
и
SIGURG
(посылается по получении внеполосных данных, см. главу 24) — это два сигнала, игнорируемых по умолчанию, с которыми мы встретимся в тексте.

Функция signal

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

sigaction
. Однако это достаточно сложно, поскольку один аргумент этой функции — это структура, для которой необходимо выделение памяти и заполнение. Поэтому проще задать действие сигнала с помощью функции
signal
. Первый ее аргумент — это имя сигнала, а второй — либо указатель на функцию, либо одна из констант
SIG_IGN
и
SIG_DFL
. Но функция
signal
существовала еще до появления POSIX.1, и ее различные реализации имеют разную семантику сигналов с целью обеспечения обратной совместимости. В то же время POSIX четко диктует семантику при вызове функции
sigaction
. Это обеспечивает простой интерфейс с соблюдением семантики POSIX. Мы включили эту функцию в нашу собственную библиотеку вместе функциями
err_ XXX
и функциями-обертками, которые мы используем для построения всех наших программ. Она представлена в листинге 5.5. Функция-обертка
Signal
здесь не показана, потому что ее вид не зависит от того, какую именно функцию
signal
она должна вызывать.

Листинг 5.5. Функция signal, вызывающая функцию POSIX sigaction

//lib/signal.c

1 #include "unp.h"

2 Sigfunc*

3 signal(int signo, Sigfunc *func)

4 {

5 struct sigaction act, oact;

6 act.sa_handler = func;

7 sigemptyset(&act.sa_mask);

8 act.sa_flags = 0;

9 if (signo == SIGALRM) {

10 #ifdef SA_INTERRUPT

11 act.sa_flags |= SA_INTERRUPT; /* SunOS 4.x */

12 #endif

13 } else {

14 #ifdef SA_RESTART

15 act.sa_flags |= SA_RESTART; /* SVR4, 44BSD */

16 #endif

17 }

18 if (sigaction(signo, &act, &oact) < 0)

19 return (SIG_ERR);

20 return (oact.sa_handler);

21 }

Упрощение прототипа функции при использовании typedef

2-3
Обычный прототип для функции
signal
усложняется наличием вложенных скобок:

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

Чтобы упростить эту запись, мы определяем тип

Sigfunc
в нашем заголовочном файле
unp.h
следующим образом:

typedef void Sigfunc(int);

указывая тем самым, что обработчики сигналов — это функции с целочисленным аргументом, ничего не возвращающие (

void
). Тогда прототип функции выглядит следующим образом:

Sigfunc *signal(int signo, Sigfunc * func);

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

Установка обработчика

6
Элемент
sa_handler
структуры
sigaction
устанавливается равным аргументу
func
функции
signal
.

Установка маски сигнала для обработчика

7
POSIX позволяет нам задавать набор сигналов, которые будут блокированыпри вызове обработчика сигналов. Любой блокируемый сигнал не может быть доставлен процессу. Мы устанавливаем элемент
sa_mask
равным пустому набору. Это означает, что во время работы обработчика дополнительные сигналы не блокируются. POSIX гарантирует, что перехватываемый сигнал всегда блокирован, пока выполняется его обработчик.

Установка флага SA_RESTART

8-17
Флаг
SA_RESTART
не является обязательным, и если он установлен, то системный вызов, прерываемый этим сигналом, будет автоматически снова выполнен ядром. (В продолжении нашего примера мы более подробно поговорим о прерванных системных вызовах.) Если перехватываемый сигнал не является сигналом
SIGALRM
, мы задаем флаг
SA_RESTART
, если таковой определен. (Причина, по которой сигнал
SIGALRM
обрабатывается отдельно, состоит в том, что обычно цель его генерации - ввести ограничение по времени в операцию ввода-вывода, как показано в листинге 14.2. В этом случае мы хотим, чтобы блокированный системный вызов был прерван сигналом.) Более ранние системы, особенно SunOS 4.x, автоматически перезапускают прерванный системный вызов по умолчанию и затем определяют флаг
SA_INTERRUPT
. Если этот флаг задан, мы устанавливаем его при перехвате сигнала
SIGALRM
.

  • Читать дальше
  • 1
  • ...
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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