Главная страница  Взаимодействие нетривиальных процессов 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 [ 37 ] 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186

Листинг 5.14 (продолжение)

24 sleepO): /* получаем сигналы */

25 ехП(О):

26 }

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

28 sleepO): /* дочерний процесс блокирует сигналы */

29 for (1 - SIGRTMAX: i >= SIGRTMAX - 2: i--) {

30 for (j - 0; j <= 2: {

31 val .sivaljnt = j:

32 Sigqueue(pid. i. val):

33 printfCsent signal %d. val = %d\n . i. j):

34 }

35 }

36 exit(O):

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.sivaljnt):

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) для установки функции sigrt в качестве обработчика трех указанных выше сигналов реального времени. Функция устанавливает флаг SA SIGINFO, и поскольку эти три сигнала являются сигналами реального времени, мы можем ожидать, что они будут обрабатываться соответствующим образом. Эта функция также устанавливает маску сигналов, блокируемых на время выполнения обработчика.

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

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



времени. Это позволяет всем помещенным в очередь сигналам достичь адресата. Затем делается пауза еще на три секунды, чтобы обработчик успел вызвать pri ntf девять раз, после чего дочерний процесс завершает свою работу.

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

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

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

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

ПРИМЕЧАНИЕ -

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

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

Solaris % testl

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

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

sent signal 45, val - О 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 =

ival

received signal

#45,

code =

ival

received signal

#45,

code =

ival

received signal

#44,

code =

ival

received signal

#44.

code =

ival

received signal

#44,

code =

ival

= 0

received signal

#43,

code =

ival

received signal

#43,

code =

ival

received signal

#43.

code =

ival

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



Кроме того, сигналы с одинаковым номером приходят в порядке LIFO, а не FIFO. Код si code = -2 соответствует SI QUEUE.

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

alplia % testl SIGRTMIN = 33,

SIGRTMAX - 48

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 alplia %

16 сигналов реального времени трехсекундная пауза

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

recei ved recei ved recei ved recei ved recei ved recei ved recei ved recei ved received

signal signal signal signal signal signal signal signal signal

#46. code

#46. code

#46, code

#47. code

#47. code

#47, code

#48, code

#48. code

#48. code

ival - 0

ival = 1

ival = 2

ival = 0

ival - 1

ival = 2

ival = 0

ival = 1

ival = 2

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

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

ПРИМЕЧАНИЕ -

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

Функция signal rt

в книге [24, с. 120] мы привели пример собственной функции signal, вызывавшей функцию si gacti on стандарта Posix для установки обработчика сигнала, обеспечивающего надежную семантику Posix. Изменим эту функцию, чтобы обеспечить поддержку реального времени. Новую функцию мы назовем signal rt; ее текст приведен в листинге 5.15.

Листинг 5.15. Функция signal rt с поддержкой реального времени

lib/signal rt.c 1 #include unpipch

Sigfunc rt *

signal rt(int signo. Sigfunc rt *func) {

struct sigaction act, oact:

act.sa sigaction - tunc: /* сохраняем адрес функции */ sigemptyset(&act. sa masl<):



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 [ 37 ] 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186

© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования.