Читать «UNIX: взаимодействие процессов» онлайн - страница 76

Уильям Ричард Стивенс

■ SI_MESGQ — сигнал был порожден при помещении сообщения в пустую очередь сообщений (как в разделе 5.6); 

■ SI_QUEUE — сигнал был отправлен функцией sigqueue. Пример будет вскоре приведен;

■ SI_TIMER — сигнал был порожден по истечении установленного функцией timer_settime времени. Эту функцию мы не описываем;

■ SI_USER — сигнал был отправлен функцией kill.

Если сигнал был порожден каким-либо другим событием, si_code будет иметь значение, отличающееся от приведенных выше. Значение поля si_value структуры siginfo_t актуально только в том случае, если si_code имеет одно из следующих значений: SI_ASYNCIO, SI_MESGQ, SI_QUEUE и SI_TIMER.

Пример

В листинге 5.14 приведен пример программы, демонстрирующей использование сигналов реального времени. Программа вызывает fork, дочерний процесс блокирует три сигнала реального времени, родительский процесс отправляет девять сигналов (три раза отсылается каждый из заблокированных сигналов), затем дочерний процесс разблокирует сигналы и мы смотрим, сколько раз будет получен каждый из них и в каком порядке они придут.

Листинг 5.14. Тестовая программа, иллюстрирующая работу с сигналами реального времени

//rtsignals/test1.c

1  #include "unpipc.h"

2  static void sig_rt(int, siginfo_t *, void *);

3  int

4  main(int argc, char **argv)

5  {

6   int i, j;

7   pid_t pid;

8   sigset_t newset;

9   union sigval val;

10  printf("SIGRTMIN = %d, SIGRTMAX = %d\n", (int) SIGRTMIN, (int) SIGRTMAX);

11  if ((pid = Fork()) == 0) {

12   /* дочерний процесс блокирует 3 сигнала */

13   Sigemptyset(&newset);

14   Sigaddset(&newset, SIGRTMAX);

15   Sigaddset(&newset, SIGRTMAX – 1);

16   Sigaddset(&newset, SIGRTMAX – 2);

17   Sigprocmask(SIG_BLOCK, &newset, NULL);

18   /* установка обработчика с флагом SA_SIGINFO */

19   Signal_rt(SIGRTMAX, sig_rt);

20   Signal_rt(SIGRTMAX – 1, sig_rt);

21   Signal_rt(SIGRTMAX – 2, sig_rt);

22   sleep(6); /* родительский процесс посылает все сигналы */

23   Sigprocmask(SIG UNBLOCK, &newset, NULL); /* разблокируемся */

24   sleep(3); /* получаем сигналы */

25   exit(O);

26  }

27  /* родительский процесс отправляет сигналы */

28  sleep(3); /* дочерний процесс блокирует сигналы */

29  for (i = SIGRTMAX; i >= SIGRTMAX – 2; i--) {

30   for (j = 0; j <= 2; j++) {

31    val.sival_int = j;

32    Sigqueue(pid, i, val);

33    printf("sent signal %d, val = %d\n", i, j);

34   }

35  }

36  exit(0);

37 }

38 static void

39 sig_rt(int signo, siginfo_t *info, void *context)

40 {

41  printf(received signal #%d, code = %d, ival = %d\n",

42   signo.info->si_code, info->si_value.sival_int);

43 }

Вывод номеров сигналов реального времени

10 Мы печатаем наибольший и наименьший номера сигналов реального времени, чтобы узнать, сколько их предоставляется в данной реализации. Мы преобразуем обе константы к типу integer, поскольку в некоторых реализациях они определяются как макросы, требующие вызова sysconf, например: