Операционная система UNIX - страница 74

стр.

диспозиция всех перехватываемых сигналов будет установлена на действие по умолчанию. Это вполне естественно, поскольку образ новой программы не содержит функции-обработчика, определенной диспозицией сигнала перед вызовом exec(2). Функция signal(3C) имеет следующее определение:

>#include

>void(*signal(int sig, void (*disp)(int)))(int);

Аргумент >sig определяет сигнал, диспозицию которого нужно изменить.

Аргумент >disp определяет новую диспозицию сигнала, которой может быть определенная пользователем функция-обработчик или одно из следующих значений:

>SIG_DFLУказывает ядру, что при получении процессом сигнала необходимо вызвать системный обработчик, т.е. выполнить действие по умолчанию.
>SIG_IGNУказывает, что сигнал следует игнорировать. Напомним, что не все сигналы можно игнорировать.

В случае успешного завершения signal(3C) возвращает предыдущую диспозицию — это может быть функция-обработчик сигнала или системные значения >SIG_DFL или >SIG_IGN. Возвращаемое значение может быть использовано для восстановления диспозиции в случае необходимости.

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

>#include


>/* Функция-обработчик сигнала */

>static void sig_hndlr(int signo) {

> /* Восстановим диспозицию */

> signal(SIGINT, sig_hndlr);

> printf("Получен сигнал SIGINT\n");

>}


>main() {

> /* Установим диспозицию */

> signal(SIGINT, sih_hndlr);

> signal(SIGUSR1, SIG_DFL);

> signal(SIGUSR2, SIG_IGN);

> /* Бесконечный цикл */

> while(1)

>  pause();

>}

В этом примере изменена диспозиция трех сигналов: >SIGINT, >SIGUSR1 и >SIGUSR2. При получении сигнала >SIGINT вызывается обработчик при получении сигнала >SIGUSR1 производится действие по умолчанию (процесс завершает работу), а сигнал >SIGUSR2 игнорируется. После установки диспозиции сигналов процесс запускает бесконечный цикл, в процессе которого вызывается функция pause(2). При получении сигнала, который не игнорируется, pause(2) возвращает значение -1, а переменная errno устанавливается равной >EINTR. Заметим, что каждый раз при получении сигнала >SIGINT мы вынуждены восстанавливать требуемую диспозицию, в противном случае получение следующего сигнала этого типа вызвало бы завершение выполнения процесса (действие по умолчанию).

При запуске программы, получим следующий результат:

>$ а.out &

>[1] 8365              PID порожденного процесса

>$ kill -SIGINT 8365

>Получен сигнал SIGINT Сигнал SIGINT перехвачен

>$ kill -SIGUSR2 8365  Сигнал SIGUSR2 игнорируется

>$ kill -SIGUSR1 8365

>[1]+ User Signal 1    Сигнал SIGUSR1 вызывает завер-

>a.out                 шение выполнения процесса

>$

Для отправления сигналов процессу использована команда kill(1), описанная в предыдущей главе.

Надежные сигналы

Стандарт POSIX. 1 определил новый набор функций управления сигналами. основанный на интерфейсе 4.2BSD UNIX и лишенный рассмотренных выше недостатков.

Модель сигналов, предложенная POSIX, основана на понятии набора сигналов (signal set), описываемого переменной типа >sigset_t. Каждый бит этой переменной отвечает за один сигнал. Во многих системах тип >sigset_t имеет длину 32 бита, ограничивая количество возможных сигналов числом 32.

Следующие функции позволяют управлять наборами сигналов:

>#include


>int sigempyset(sigset_t *set);

>int siufillset(sigset_t *set);

>int sigaddset(sigset_t *set, int signo);

>int sigdelset(sigset_t *set, int signo);

>int sigismember(sigset_t *set, int signo);

В отличие от функции signal(3C), изменяющей диспозицию сигналов, данные функции позволяют модифицировать структуру данных