[<<Previous Entry] [^^Up^^] [Next Entry>>] [Menu] [About The Guide]
 SVR4 - Новые методы управления сигналами

sigaction(2)
Системный вызов sigaction(2) дает ранее недоступный уровень управления
сигналами. Кроме  того, он  совместим с  требованиями стандарта POSIX.
sigaction(2)  предоставляет   возможности,   ранее   реализованные   в
sigset(2): закрывает   окно  уязвимости при  использовании signal(2) и
автоматически блокирует  рекурсивный вызов  функции обработки сигнала.
Параметры act  и oact, если они не равны нулю, указывают на экземпляры
struct sigaction со следующими полями:

  void (*sa_handler)(); - Адрес функции обработки сигнала, SIG_IGN или
                         SIG_DFL

  sigset_t sa_mask -     Маска   сигналов,    которые   должны    быть
                         заблокированы,   когда   вызывается   функция
                         обработки сигнала.

  int sa_flags -         Флаги, управляющие доставкой сигнала.

Если аргумент  act ненулевой,  он указывает на структуру, определяющую
новые действия,  которые должны быть предприняты при получении сигнала
sig. Если  аргумент oact  ненулевой, он  указывает на  структуру,  где
сохраняются ранее установленные действия для этого сигнала.

Поле sa_flags  в struct  sigaction формируется побитовым ИЛИ следующих
значений:

  SA_ONSTACK -    Используется    для     обработки    сигналов     на
                  альтернативном сигнальном стеке.

  SA_RESETHAND -  Во время  исполнения  функции  обработки  сбрасывает
                  реакцию на  сигнал к  SIG_DFL; обрабатываемый сигнал
                  при этом не блокируется.

  SA_NODEFER -    Во время обработки сигнала сигнал не блокируется.

  SA_RESTART -    Системные вызовы, которые будут прерваны исполнением
                  функции обработки, автоматически перезапускаются.

  SA_SIGINFO -    Используется для  доступа к  подробной информации  о
                  процессе, исполняющем  сигнальный обработчик,  такой
                  как  причина   возникновения  сигнала   и   контекст
                  процесса в момент доставки сигнала.

  SA_NOCLDWAIT -  Подавляет создание процессов-зомби.

  SA_NOCLDSTOP -  Подавляет  генерацию   SIGCHLD,  когда   порожденные
                  процессы останавливаются или возобновляются.
              SVR4 - НОВЫЕ МЕТОДЫ УПРАВЛЕНИЯ ПРОЦЕССАМИ

sigaction(2)

ИМЯ

          sigaction - новый метод обработки сигналов



ИСПОЛЬЗОВАНИЕ

        #include <signal.h>

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



ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ

          успех - 0

          неуспех - -1 и errno установлена
                        sigaction(2) - Пример

Эта программа является пересмотренным примером, который был приведен в
этом разделе раньше.

13-17     Объявляется экземпляр  struct sigaction; ее поле sa_handler,
          которое определяет  реакцию, инициализируется именем функции
          обработки сигнала;  sbgaction(2)  вызывается  для  перехвата
          SIGINT.

Файл: primes1.sa.c
                        sigaction(2) - ПРИМЕР


 1         #include <stdio.h>
 2         #include <signal.h>
 3         #define   OUTPUT   "Primes"
 4         #define   MAXNUM   10000
 5
 6         int count;
 7         FILE *fptr;
 8
 9         main()
10         {
11         int number, divisor;
12         void sigcatch(int);
13         static struct sigaction term;
14
15         fptr = fopen(OUTPUT, "w");
16         term.sa_handler = sigcatch;
17         sigaction(SIGINT, &term, NULL);
   ...
26         }
27         fclose(fptr);
28         }
29
30
31         void sigcatch(int sig)
32         {
33         printf("%d primes computed\n", count);
34         fclose(fptr);
35         exit(1);
36         }
         sigaction(2) - Пример - Перезапуск системного вызова

Эта программа демонстрирует перезапуск системного вызова.

13-16     Инициализируются   поля   структуры   act.   Поле   sa_flags
          установлено так, чтобы включать флаг SA_RESTART.

16        sigaction(2) вызывается,  чтобы установить функцию обработки
          SIGINT.

19        read(2)    при    чтении    с    терминального    устройства
          удовлетворяется вводом  символа перевода  строки. Мы  видели
          ранее, что  реакция read(2)  по умолчанию в случае перехвата
          SIGINT  -   неудача.  Однако,   установка  SA_RESTART  будет
          заставлять прерванный  read(2)  перезапускаться  без  потери
          данных.

Файл: input_sa.c
         sigaction(2) - ПРИМЕР - ПЕРЕЗАПУСК СИСТЕМНОГО ВЫЗОВА


 1        #include <sys/types.h>
 2        #include <stdio.h>
 3        #include <signal.h>
 4        #include <stdlib.h>
 5
 6        main()
 7        {
 8        void sigcatch(int);
 9        char buf[BUFSIZ];
10        int n;
11        struct sigaction act;
12
13        sigemptyset(&act.sa_mask);
14        act.sa_handler = sigcatch;
15        act.sa_flags = SA_RESTART;
16        if(sigaction(SIGINT, &act, NULL) == -1);
17        perror("sigaction");
18
19        n = read(0, buf, BUFSIZ);
20        if(n == -1)
21        perror("read");
22        printf("n: %d\n", n);
23        write(1, buf, n);
24        exit(0);
25        }
26
27        void sigcatch(int sig)
28        {
29        printf("signal %d received\n", sig);
30        }
         sigaction(2) - Пример - Перезапуск системного вызова

Эта  программа   пытается  установить  исключающую  блокировку  файла,
используя   системную    установку   fcntl(2)    для    того,    чтобы
приостановиться, если  какой-то другой  процесс ранее запер этот файл.
Эта программа  устанавливает перехват SIGINT с флагами, установленными
для перезапуска системного вызова, прерванного перехватом сигнала.

13-15     Инициализируется  структура   sigaction.  В   поле  sa_flags
          устанавливается флаг автоперезапуска.

24-26     Структура flock  инициализируется для  установки исключающей
          блокировки всего файла.

27-30     Программа  пытается  установить  блокировку  файла.  Команда
          F_SETLKW заставляет  fcntl(2) останавливаться, если какой-то
          другой процесс  установил блокировку  любого  участка  этого
          файла.  Так   как  вызовы   управления  сигналов  установили
          SA_RESTART,  эта   программа  при   получении  SIGINT  будет
          возобновлять попытку  блокировки в строке 27, вместо реакции
          по умолчанию: неуспеха системного вызова fcntl(2).

Программа для установки начальной блокировки такова:

#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <stdio.h>
main(int argc, char **argv)
{
               struct flock lock;
               int fd;
               if((fd = open(argv[1], O_RDONLY)) == -1) {
               perror(argv[1]);
               exit(1);
               }
               lock.l_type = F_RDLCK;
               lock.l_whence = 0;
               lock.l_start = 0L;
               lock.l_len = 0L;
               if(fcntl(fd, F_SETLK, &lock) == -1) {
               perror("Can't lock");
               exit(2);
               }
               printf("%s got lock on %s\n", argv[0], argv[1]);
               sleep(60);
               printf("%s releasing lock on %s\n", argv[0], argv[1]);
}

Файлы: lockfl.c lock_sa.c
         sigaction(2) - ПРИМЕР - ПЕРЕЗАПУСК СИСТЕМНОГО ВЫЗОВА

 1        #include <sys/types.h>
 2        #include <fcntl.h>
 3        #include <stdio.h>
 4        #include <signal.h>
 5        #include <sys/stat.h>
 6        main(int argc, char **argv)
 7        {
 8        struct flock lock;
 9        int fd;
10        void sigcatch(int);
11        struct sigaction act;
12
13        if(sigemptyset(&act.sa_mask) == -1)
14        perror("sigemptyset");
15        act.sa_handler = sigcatch;
16        act.sa_flags = SA_RESTART;
17        if(sigaction(SIGINT, &act, NULL) == -1)
18        perror("sigaction");
19
20        if((fd = open(argv[1], O_RDWR)) == -1) {
21        perror(argv[1]);
22        exit(1);
23        }
24        lock.l_type = F_WRLCK;
25        lock.l_whence = 0;
26        lock.l_len = lock.l_start = 0L;
27        if(fcntl(fd, F_SETLKW, &lock) == -1) {
28        perror("Lock attempt failed");
29        exit(2);
30        }
31        printf("%s Got lock on %s\n", argv[0], argv[1]);
32        exit(0);
33        }
34
35        void sigcatch(int sig)
36        {
37        printf("signal %d received\n", sig);
38        }