Операционная система 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), изменяющей диспозицию сигналов, данные функции позволяют модифицировать структуру данных