Пример

Пример

В листинге 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 ", (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 ", 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 ",

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

43 }

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

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

#define SIGRTMAX (sysconf(_SC_RTSIG_MAX))

и функция sysconf возвращает целое типа long (см. упражнение 5.4).

Вызов fork и блокирование трех сигналов реального времени

11-17 Запускается дочерний процесс, который вызывает sigprocmask для блокировки трех используемых сигналов реального времени: SIGRTMAX, SIGRTMAX-1 и SIGRTMAX-2.

Установка обработчика сигнала

18-21 Мы вызываем функцию signal_rt (приведенную в листинге 5.15) для установки функции sig_rt в качестве обработчика трех указанных выше сигналов реального времени. Функция устанавливает флаг SA_SIGINFO, и поскольку эти три сигнала являются сигналами реального времени, мы можем ожидать, что они будут обрабатываться соответствующим образом. Эта функция также устанавливает маску сигналов, блокируемых на время выполнения обработчика.

Ожидание порождения сигналов родительским процессом, разблокирование сигналов

22-25 Дочерний процесс ждет 6 секунд, пока родительский породит девять сигналов. Затем вызывается sigprocmask для разблокирования трех сигналов реального времени. Это позволяет всем помещенным в очередь сигналам достичь адресата. Затем делается пауза еще на три секунды, чтобы обработчик успел вызвать printf девять раз, после чего дочерний процесс завершает свою работу.

Родительский процесс отправляет девять сигналов

27-36 Родительский процесс ждет три секунды, пока дочерний не заблокирует все требуемые сигналы. Затем родительский процесс порождает три экземпляра каждого из трех сигналов реального времени: i принимает 3 значения, a j принимает значения 0, 1 и 2 для каждого из значений i. Мы преднамеренно порождаем сигналы начиная с наибольшего номера, поскольку ожидаем, что они будут получены начиная с наименьшего. Мы также отсылаем с каждым из сигналов новое значение sigval_int, чтобы проверить, что копии одного и того же сигнала доставляются в том же порядке, в каком они были отправлены, то есть очередь действительно является очередью.

Обработчик сигнала

38-43 Обработчик сигнала просто выводит информацию о полученном сигнале.

ПРИМЕЧАНИЕ

Из табл. 5.1 следует, что функция printf не относится к функциям типа async-signal-safe и не должна вызываться из обработчика сигналов. Здесь мы используем ее исключительно в качестве проверочного средства в маленькой тестовой программе. 

Запустим эту программу в Solaris 2.6. Результат будет не тем, которого мы ожидали:

solaris % test1

SIGRTMIN = 38, SIGRTMAX = 45 8 сигналов реального времени

                             трехсекундная пауза

sent signal 45, val = 0

sent signal 45, val = 1

sent signal 45, val = 2

sent signal 44, val = 0

sent signal 44, val = 1

sent signal 44, val = 2

sent signal 43, val = 0

sent signal 43, val = 1

sent signal 43, val = 2

solaris % родительский процесс завершил работу, пауза 3 секунды,

          пока дочерний процесс не разблокирует сигналы

received signal #45, code = –2, ival = 2 дочерний процесс получает сигналы

received signal #45, code = –2, ival = 1

received signal #45, code = –2, ival = 0

received signal #44, code = –2, ival = 2

received signal #44, code = –2, ival = 1

received signal #44, code = –2, ival = 0

received signal #43, code = –2, ival = 2

received signal #43, code = –2, ival = 1

received signal #43, code = –2, ival = 0

В очередь помещаются девять сигналов, но первыми принимаются сигналы с большими номерами (а мы ожидали получить сигналы с меньшими номерами). 

Кроме того, сигналы с одинаковым номером приходят в порядке LIFO, а не FIFO. Код si_code = –2 соответствует SI_QUEUE.

Запустив программу в Digital Unix 4.0B, мы получим именно тот результат, которого ожидали:

alpha % test1

SIGRTMIN = 33, SIGRTMAX = 48 16 сигналов реального времени

                             трех секундная пауза

sent signal 48, val = 0

sent signal 48, val = 1

sent signal 48, val = 2

sent signal 47, val = 0

sent signal 47, val = 1

sent signal 47, val = 2

sent signal 46, val = 0

sent signal 46, val = 1

sent signal 46, val = 2

alpha % родительский процесс завершил работу, пауза 3 секунды.

        пока дочерний процесс не разблокируетсигналы

received signal #46, code – –1, ival = 0 дочерний процесс получает сигналы

received signal #46, code = –1, ival = 1

received signal #46, code = –1, ival = 2

received signal #47, code – –1, ival = 0

received signal #47, code = –1, ival = 1

received signal #47, code = –1, ival = 2

received signal #48, code = –1, ival = 0

received signal #48, code = –1, ival = 1

received signal #48, code = –1, ival = 2

Девять сигналов помещаются в очередь и получаются адресатом в ожидаемом порядке: первым приходит сигнал с меньшим номером, а копии сигнала приходят в порядке FIFO.

ПРИМЕЧАНИЕ

Похоже, что в реализации Solaris 2.6 есть ошибка.

Поделитесь на страничке

Следующая глава >

Похожие главы из других книг

Пример

Из книги Обработка событий в С++ автора Клюев Александр

Пример В примере создаются два класса обработчик и инициатор события, устанавливается связь между ними и иллюстрируется обработка события в нескольких объектах одновременно:#include "stdafx.h" #include "sigslot.h"struct EventRaiser { // источник события signal<const char*> event; // const char* – тип аргумента.


25.5. Пример

Из книги Разработка приложений в среде Linux. Второе издание автора Джонсон Майкл К.

25.5. Пример Для закрепления материала этой главы ниже приводится пример приложения, в котором задействовано большинство функциональных возможностей qdbm. Подразумевается, что в результате выполнения этого приложения будет создана простая база данных телефонных номеров,


27.1.1. Пример

Из книги Искусство программирования на языке сценариев командной оболочки автора Купер Мендель

27.1.1. Пример В главе 8 был представлен пример использования обычной разделяемой библиотеки. Библиотеку libhello.so, которую нам удалось создать, можно загружать во время выполнения. Программа loadhello загружает libhello.so динамически и вызывает функцию print_hello, которая находится в


Пример 10-27. Простой пример сравнения строк

Из книги Программирование для Linux. Профессиональный подход автора Митчелл Марк

Пример 10-27. Простой пример сравнения строк #!/bin/bash# match-string.sh: простое сравнение строкmatch_string (){ MATCH=0 NOMATCH=90 PARAMS=2 # Функция требует два входных аргумента. BAD_PARAMS=91 [ $# -eq $PARAMS ] || return $BAD_PARAMS case "$1" in "$2") return $MATCH;; * ) return $NOMATCH;; esac}a=oneb=twoc=threed=twomatch_string $a # неверное число


Пример 12-20. Пример форматирования списка файлов в каталоге

Из книги UNIX: разработка сетевых приложений автора Стивенс Уильям Ричард

Пример 12-20. Пример форматирования списка файлов в каталоге #!/bin/bash# За основу сценария взят пример "man column".(printf "PERMISSIONS LINKS OWNER GROUP SIZE DATE TIME PROG-NAME " ; ls -l | sed 1d) | column -t# Команда "sed 1d" удаляет первую строку, выводимую командой ls,#+ (для локали "С" это строка: "total N",#+ где "N" -- общее


Пример 12-45. Пример работы с m4

Из книги UNIX — универсальная среда программирования автора Пайк Роб

Пример 12-45. Пример работы с m4 #!/bin/bash# m4.sh: Демонстрация некоторых возможносией макропроцессора m4# Строкиstring=abcdA01echo "len($string)" | m4 # 7echo "substr($string,4)" | m4 # A01echo "regexp($string,[0-1][0-1],&Z)" | m4 # 01Z# Арифметикаecho "incr(22)" | m4 # 23echo "eval(99 / 3)" | m4 #


Пример 24-2. Еще один пример проверки аргументов с помощью "И-списков"

Из книги автора

Пример 24-2. Еще один пример проверки аргументов с помощью "И-списков" #!/bin/bashARGS=1 # Ожидаемое число аргументов.E_BADARGS=65 # Код завершения, если число аргументов меньше ожидаемого.test $# -ne $ARGS && echo "Порядок использования: `basename $0` $ARGS аргумент(а)(ов)" && exit $E_BADARGS# Если


Пример 25-8. Пример реализации алгоритма Решето Эратосфена

Из книги автора

Пример 25-8. Пример реализации алгоритма Решето Эратосфена #!/bin/bash# sieve.sh# Решето Эратосфена# Очень старый алгоритм поиска простых чисел.# Этот сценарий выполняется во много раз медленнее# чем аналогичная программа на C.LOWER_LIMIT=1 # Начиная с 1.UPPER_LIMIT=1000 # До 1000.# (Вы можете


9.4. Пример

Из книги автора

9.4. Пример В архитектуре x86 есть инструкции, определяющие позицию старшего и младшего значащих битов в слове. Процессор выполняет эти инструкции очень быстро. С другой стороны, чтобы сделать то же самое на языке С, потребуется написать цикл с операциями побитового


Пример

Из книги автора

Пример В листинге 11.1[1] показана простая программа, вызывающая функцию gethostbyname для любого числа аргументов командной строки и выводящая всю возвращаемую информацию.Листинг 11.1. Вызов функции и вывод возвращаемой информации//names/hostent.c 1 #include "unp.h" 2 int 3 main(int argc, char **argv) 4 { 5  char


Пример

Из книги автора

Пример Сначала приведем пример с Ipv4:freebsd % traceroute www.unpbook.comtraceroute to www.unpbook.com (206.168.112.219): 30 hops max. 24 data bytes1 12.106.32.1 (12.106.32.1) 0.799 ms 0.719 ms 0.540 ms2 12.124.47.113 (12.124.47.113) 1.758 ms 1.760 ms 1.839 ms3 gbr2-p27.sffca.ip.att.net (12.123.195.38) 2.744 ms 2.575 ms 2.648 ms4 tbr2-p012701.sffca.ip.att.net (12.122.11.85) 3.770 ms 3.689 ms 3.848 ms5 gbr3-p50.dvmco.ip.att.net (12.122.2.66) 26.202 ms 26.242 ms


Пример

Из книги автора

Пример Сначала мы запустим нашу программу с аргументом командной строки -0 и убедимся, что сервер имен отвечает на приходящие дейтаграммы, не содержащие контрольной суммы. Мы также задаем флаг -v.macosx # udpcksum -i en1 -0 -v bridget.rudoff.com domaindevice = en1local net = 172.24.37.64. netmask = 255.255.255.224cmd = udp and src host