102.92K
Категория: ПрограммированиеПрограммирование

Сигналы

1.

Приложения
Сигналы
kill(i)
raise(i)
sigqueue(i)
«Железо»
Shell
kill -9 <pid>
Процесс I
Процесс J
KB: Ctrl_C
Ядро
«Сигнал»
1
2
Обработка_1
...
3
...
63
Процедура
обработки
64
Обработка_64
1–40 POSIX–сигналы общего назначения
SIGINT [2] Ctrl-C
SIGDEADLK [7] mutex deadlock
41–56 POSIX–сигналы реального
SIGKILL [9] kill -9 <pid>
времени
(не перехватывается!)
SIGFPE [8] float point exception 57-64 «Специальные сигналы»
SIGUSR1 [16] и SIGUSR2 [17] - пользовательские
Сигналы
2016 v.01
1

2.

Обработка сигналов («перехват»)
Инициализация набора сигналов
sigset_t – маска, определяющая набор сигналов и «блокирован/нет»
sigemptyset(sigset_t* set) – инициализация пустого набора;
sigaddset(sigset_t* set, int sig) – добавление к набору сигнала sig;
sigfillset(sigset_t* set) – инициализация набора со всеми сигналами;
sigdelset(sigset_t* set, int sig) – исключение sig из набора.
Работа с «маской»
(возможность блокировки на время работы критической секции)
#include <signal.h>
int sigprocmask( int how, const sigset_t * set, sigset_t * oset);
sig – сигнал; set – значение маски; oset – предыдущее значение маски
how – SIG_BLOCK – блокировать сигналы set, SIG_UNBLOCK разблокировать
сигналы set, SIG_SETMASK переустановить сигналы на значения в set
//
//
sigset_t set;
sigemptyset( &set );
sigaddset(&set, SIGINT);
sigaddset(&set, SIGUSR1);
sigprocmask(SIG_BLOCK, &set, NULL); между процессами
pthread_sigmask(SIG_BLOCK, &set, NULL); между потоками
Сигналы
2020 v.01
2

3.

Инициализация «способа обработки»
#include <signal.h>
int sigaction( int sig, const struct sigaction * act, struct
sigaction * oact );
sig – сигнал; act – «способ обработки»; oact – структура для
сохранения предыдущего «способа обработки»
Способ обработки сигнала
struct sigaction {
union {
void (*sa_handler)(int sig);
void (*sa_sigaction)(int sig, siginfo_t* info, void* other);
}
sigset_t sa_mask;
int sa_flags;
}
sa_handler – функция–обработчик сигнала sig;
sa_mask – указывает на набор сигналов, к которому относится sig;
будут блокироваться при работе Обработчика;
sa_flags – 0 – сигналы «no queued», SA_SIGINFO – сигналы «реального
времени», для которых используется обработчик sa_sigaction
Сигналы
2016 v.01
3

4.

#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
void catchint(int signo) {
printf("SIGINT: signo = %d\n", signo);
}
int main() {
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGINT);
struct sigaction act;
act.sa_handler = &catchint;
act.sa_flags = 0;
act.sa_mask = set;
sigaction(SIGINT, &act, NULL);
int i;
for(i=0; i<5; i++) {
sleep(1);
if ( i==3) raise(SIGINT);
printf("Cycle # %d\n", i );
}
}
Сигналы
2016 v.01
Пример
Процесс посылает сигнал
SIGINT [2] «сам себе»
Cycle # 0
Cycle # 1
Cycle # 2
SIGINT: signo = 2
Cycle # 3
Cycle # 4
4

5.

Сигналы «реального времени»
Сигналы с номерами SIGRTMIN – SIGRTMAX (41 – 56)
«Генерация» с помощью функции:
•int sigqueue (pid_t pid, int sig, const union sigval value);
• FIFO очередность приема для одного и того же посланного сигнала
• Для сигналов с разными номерами приоритет у более низкого номера
(?!)
• Отправитель может переслать с сигналом 32-х битное значение
• Функция обработчика:
void sa_sigaction (int sig, siginfo_t* info, void* context);
typedef struct {
. . .
int si_signo;
int si_code; /* определяется типом отправителя */
union sigval si_value;
union sigval {
. . .
int sival_int;
} siginfo_t
void* sival_ptr;
}
Сигналы
2016 v.01
5

6.

Пример
void handler(int signo, siginfo_t* info, void* context) {
printf("signo=%d, code=%d, info=%d\n",
signo, info->si_code, info->si_value.sival_int);
}
int main() {
int signal = 48, value = 777;
sigset_t set;
sigemptyset(&set);
sigaddset(&set, signal);
sigprocmask(SIG_BLOCK, &set, NULL);
pid_t pid;
if(pid = fork() != 0) {
/* процесс – родитель */
siginfo_t info;
info.si_value.sival_int = value;
sigqueue(0, signal, info.si_value);
printf("signal #%d, value %d is sent\n“, signal, info.si_value);
printf("Parent (pid=%d) finished\n", pid);
}
13. Сигналы
2016 v.01
6

7.

Пример (продолжение)
/* дочерний процесс */
else {
printf("Child (pid=%d):
started ...\n");
struct sigaction act;
act.sa_sigaction = &handler;
act.sa_flags = SA_SIGINFO;
act.sa_mask = set;
sigaction(signal, &act, NULL);
printf("Child (pid=%d): signal unblocked", pid);
sigprocmask(SIG_UNBLOCK, &set, NULL);
}
Parent (pid=1) started
Child (pid=0) started ...
signal #48, value 777 is sent
Child (pid=0): signal unblocked
Parent (pid=1) finished
signo = 48, code = -2, info = 777
Child (pid=0) finished
13. Сигналы
2016 v.01
7
English     Русский Правила