- •Лекция-1:
- •Лекция-2:
- •Лекция-3:
- •Лекция-4:
- •Лекция-5:
- •Лекция-6:
- •Лекция-7:
- •Лекция-8:
- •Лекция-9:
- •Лекция-10:
- •Лекция-11:
- •Лекция-12:
- •Лекция-13:
- •Лекция-14:
- •Лекция-14:
- •Лекция-15:
- •Лекция-16:
- •Лекция-17:
- •Лекция-18:
- •Лекция-19:
- •Применение алгоритма банкира
- •Лекция-20:
- •Лекция-21
- •Лекция-22
- •Лекция-23
- •Лекция-24
Лекция-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);
Функция sigemptyset инициализирует набор, очищая все биты.
Функция sigfillset устанавливает в набор все сигналы, известные системе.
Функции sigaddset добавляет сигнал в набор.
Функции sigdelset удаляет сигнал из набора.
Функция 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();
}