3. Надежные сигналы
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
void (*mysig(int sig, void(*handler)(int))) (int) {
struct sigaction act;
act.sa_handler=handler;
sigemptyset(&act.sa_mask);
sigaddset(&act.sa_mask, SIGINT);
act.sa_flags=0;
if(sigaction(sig, &act, 0) < 0) {
return(SIG_ERR);
}
return(act.sa_handler);
}
void handler(int nomer) {
const int time = 30;
printf("SIGINT: is blocked\n");
sleep(time);
printf("SIGINT: is ready\n");
}
int main( void ) {
mysig( SIGUSR1, handler);
pause();
signal(SIGUSR1,handler);
pause();
printf("end\n");
return 0;
}
Листинг 3. Программа sigact.c
В начале программы мы реализуем диспозицию сигналов, устанавливая в соответствие маскированию прерывания обработчик пользовательского сигнала SIGUSR1. По приходу которого, сигнал INT блокируется временно, после чего исполняется. Блокировка выполнена в виде ‘засыпания’ процесса. После окончания блокировки, при условии, что поступал сигнал SIGINT, он тут же обрабатывается.
Запуск и анализ результатов:
$gcc -o sig_1 sigact.c
$ ./sig_1&
[1] 5206057
$ pidin -p 5206057
pid tid name prio STATE Blocked
5206057 1 ./sig_1 10r SIGWAITINFO
Как видно, процесс существует. Пошлем ему сигнал, инициирующий маскирование:
$ kill -s SIGUSR1 5206057
SIGINT: is blocked
$ kill -s SIGINT 5206057
$ pidin -p 5206057
pid tid name prio STATE Blocked
5206057 1 ./sig_1 10r NANOSLEEP
Мы видим, сигнал был заблокирован, и после его поступления наш процесс еще существует в состоянии NANOSLEEP. Теперь, по окончанию маскирования, проверим таблицу процессов:
SIGINT: is ready
$ pidin -p 5206057
pid tid name prio STATE Blocked
pidin: couldn't open /proc/5206057/as: No such file or directory
[1] + Interrupt ./sig_1
Процесс был уничтожен пришедшим прерыванием.
Сравнивая разные методы реализации сигналов, можно сказать, что в случае ‘ненадежных’, пользователь заведомо не имеет возможности контролировать привязку обработчика к сигналу. По умолчанию, обработчик сработает. Однако существует ряд сигналов, которые нельзя перехватить. В случае ‘надежных’ сигналов, мы работаем со структурой sigact. А именно, обнулив флаги, влияющие на поведение сигнала, мы привязываем к нему обработчик посредством функции sigaction(sig, &act, 0), которая проверяет на наличие ошибок, и в случае некорректной привязки, формирует сигнал SIG_ERR. Таким образом, пользователь имеет однозначное представление о факте привязки его обработчика к сигналу.
4. Надежные сигналы. Модификация
#include <stdio.h> <stdlib.h> <signal.h> <sys/types.h> <sys/stat.h> <fcntl.h> <unistd.h>
void (*mysig(int sig, void(*handler)(int))) (int) {
struct sigaction act,oldact;
act.sa_handler=handler;
sigemptyset(&act.sa_mask);
sigaddset(&act.sa_mask, SIGINT);
act.sa_flags=0;
if(sigaction(sig, &act, &oldact) < 0) {
return(SIG_ERR);
}
return(oldact.sa_handler);
}
void handler(int nomer) {
printf("SIGINT: is blocked\n");
kill(getpid(),SIGINT);
sleep(30);
printf("SIGINT: is ready\n");
}
int main( void ) {
void *oldhnd;
oldhnd = mysig( SIGUSR1, handler);
pause();
signal(SIGUSR1,handler);
pause();
printf("end\n");
return 0;
}
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.