Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Конспект 17 страниц.doc
Скачиваний:
14
Добавлен:
15.06.2014
Размер:
826.37 Кб
Скачать

Лекция-8:

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

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

#include <signal.h>

int sigemptyset (sigset_t *set);

int sigfillset (sigset_t *set);

int sigaddset (sigset_t *set, int signo);

int sigdelset (sigset_t *set, int signo);

int sigismember (sigset_t *set, int signo);

  1. Функция sigemptyset инициализирует набор, очищая все биты.

  2. Функция sigfillset устанавливает в набор все сигналы, известные системе.

  3. Функции sigaddset добавляет сигнал в набор.

  4. Функции sigdelset удаляет сигнал из набора.

  5. Функция sigismember проверяет, входит ли сигнал signo в набор.

Стандартом также определён системный вызов

int sigaction(int sig struct sigaction *act, struct sigaction *oact);

который позволяет установить диспозицию сигнала, узнать её текущее значение или выполнить то и другое одновременно. В этой функции вся необходимая информация передаётся через указатель на структуру типа sigaction, которая имеет следующие поля:

struct sigaction

{

void (*sa_handler)();

void (*sa_sigaction)(int, siginfo_t *, void *);

sigset_t sa_mask;

int sa_flags;

}

  • первое поле определяет обработчик сигналов

  • второе поле  обработка сигналов, если установлен флаг SA_SIGINFO

  • третье поле  маска сигналов

  • четвёртое поле  поле флагов

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

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

SIG_DFL  обратботчик по умолчанию

<АДРЕС>  адрес обработчика

Если поля sa_handler и sa_sigaction не равны NULL то sa_mask содержит набор сигналов, которые будут добавлены к маске сигналов перед вызовом обработчика.

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

Поле sa_flags определяет флаги, которые определяют способ доставки сигнала:

SA_ONSTACK  если определена функция-обработчик сигнала и с помощью функции sigaltstack() задан альтернативный стек для функции-обработчика, то при обработке сигнала будет использоваться этот стек. Если флаг не установлен, будет использоваться обычный стек процесса;

SA_RESETHAND  если определена функция-обработчик, то реакция на сигнал будет изменена на SIG_DFL и сигнал не будет блокироваться при запуске обработчика. Если флаг не установлен, то реакция на сигнал не изменяется.

SA_NODEFERR  если определена функция-обработчик, то сигнал блокируется на время обработки только в том случае, когда он явно указан в поле sa_mask. Если флаг не установлен, то в процессе обработки данный сигнал автоматически блокируется в процессе обработки.

SA_RESTART  если определена функция-обработчик, то ряд системных вызовов, выполнение которых было прервано полученным сигналом, будет автоматически запущен после обработки сигнала. К таким системным вызовам относятся: write, read. Если флаг не установлен, то системный вызов возвращает ошибку: EINTR (ошибка прерывания).

SA_SIGINFO  если указана реакция на перехват сигнала, то вызывается функция обработчик определенная sa_sigaction. Если флаг не установлен, то вызывается функция обработчик определенная полем sa_handler.

SA_NOCLDWAIT  если указанный аргументом sig сигнал равен SIGCHLD, то при завершении потомки не будут переходить в состояние “зомби”. Если процесс в дальнейшем вызовет одну из функций семейства wait, их выполнение будет блокировано до завершения работы всех потомков данного процесса.

SA_NOCLDSTOP  если sig==SIGCHLD, то указанный сигнал не будет отправляться процессу при завершении или остановке любого из его потомков.

Если установлен SA_SIGINFO, то при получении сигнала будет вызван обработчик, адресованный sa_sigaction.

Обработчику передаётся номер сигнала и указатель на структуру типа siginfo_t, содержащую информацию о причинах получения сигнала, а также указатель на структуру типа ucontext_t, содержащую контекст процесса.

struct siginfo_t

si_signo  номер сигнала

si_errno  номер ошибки

si_code  причина отправления сигнала: если si_code <= 0, то сигнал был отправлен прикладным процессом и si_id и si_uid содержат значения процесса, пославшего сигнал. Если значение si_code > 0, то оно указывает на причину отправления сигнала.

Системный вызов sigprocmask позволяет получить и установить текущую маску сигналов: int sigprocmask (int how, sigset_t *set, sigset_t *oset);

Параметр how может принимать значения:

  • SIG_BLOCK  результирующая маска получается путем объединения текущих сигналов и set

  • SIG_UNBLOCK  результирующая маска получается путем удаления set из текущей маски

  • SIG_SETMASK  маска будет заменена на set

Если набор set==NULL, то первый атрибут игнорируется, а если oset!=NULL, то по указанному адресу помещается текущая маска сигналов.

Системный вызов sigpending используется для получения набора заблокированных сигналов и сигналов, ждущих передачи: int sigpending (sigset_t *set);

Системный вызов sigsuspend замещает текущую маску набором set и приостанавливает выполнение процесса до получения сигналов, диспозиция которых установлена, либо на завершение процесса, либо на вызов функции-обработчика: int sigsuspend (const sigset_t *set );

#include <signal.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <unistd.h>

void (*mysignal (int signo, void (*hndlr)(int)))

{

struct sigaction act, oact;

act.sa_handler=hndlr;

sigemptyset(&act.sa_mask);

act.sa_flags=0;

if (signo != SIGALARM) act.sa_flags |= SA_RESTART;

if (sigaction(signo, &act, &oact) < 0) return (SIG_ERR);

return (oact.sa_handler);

}

static void sig_hndlr(int signo)

{

printf(“Получен сигнал %i \n”,signo);

}

main()

{

mysignal(SIGINT, sig_hndlr);

mysignal(SIGUSR1, SIG_DFL);

mysignal(SIGUSR2, SIG_IGN);

while(1)

pause();

}