Средства межпроцессорного взаимодействия, страница 3

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;

}