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

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.1 (продолжение)

alarm

getegid

setgid

tcflush

cfgetispeed

geteuid

setpgid

tcgetattr

cfgetospeed

getgid

setsid

tcgetgrp

cfsetispeed

getgroups

setuid

tcsendbreak

cfsetospeed

getpgrp

sigaction

tcsetattr

chdir

getpid

sigaddset

tcsetpgrp

chmod

getppid

sigdelset

time

chown

getuid

sigemptyset

timer getoverrun

clockgettime

kill

sigfillset

timer gettime

close

link

sigismember

timer settime

creat

Iseek

signal

times

mkdir

sigpause

umask

dup2

mkfifo

sigpending

uname

execle

open

sigprocmask

unlink

execve

pathconf

sigqueue

utime

exit

pause

sigset

wait

fcntl

pipe

sigsuspend

waitpid

fdatasync

raise

sleep

Write

fork

read

stat

Пример: уведомление сигналом

Одним из способов исключения вызова 1?аких-либо функций из обработчика сигнала является установка этим обработчиком глобального флага, который проверяется программным потоком для получения информации о приходе сообщения. В листинге 5.9 иллюстрируется этот метод, хотя новая программа также содержит ошибку, но уже другую, о которой мы вскоре поговорим подробнее.

Глобальная переменная

2 Поскольку единственное действие, выполняемое обработчиком сигнала, заключается в присваивании ненулевого значения флагу mqflag, глобальным переменным из листинга 5.8 уже не нужно являться таковыми. Уменьшение количества глобальных переменных - это всегда благо, особенно при использовании программных потоков.

Открытие очереди сообщений

15-18 Мы открываем очередь сообщений, получаем ее атрибуты и выделяем буфер считывания.

Инициализация наборов сигналов

19-22 Мы инициализируем три набора сигналов и устанавливаем бит для сигнала SIGUSRl в наборе newmask.

Установка обработчика сигнала, включение уведомления

23-27 Мы устанавливаем обработчик сигнала для SIGUSRl, присваиваем значения полям структуры sigevent и вызываем mq noti fy.



Листинг 5.9. Обработчик сигнала устанавливает флаг для главного потока (неправильная версия)

pxmsg/mqnot i fy S1g2.с

1 #include unpipc.h

2 volatile sig atoniic t mqflag: /* ненулевое значение устанавливается обработчиком */

3 static void sig usrl(int):

4 int

5 main(int argc, char **argv)

7 mqd t mqd:

8 void *buff:

9 ssize t n:

10 sigset t zeromask, newmask, oldmask;

11 struct mq attr attr:

12 struct sigevent sigev:

13 if (argc != 2)

14 err quit( usage: mqnbtifysig2 <name> );

15 /* открытие очереди, получение атрибутов, выделение буфера */

16 mqd - Mq open(argv[l], 0 ROONLY):

17 Mq getattr(mqd, &attr):

18 buff - Malloc(attr.mq msgsize):

19 Sigemptyset(&zeromask): /* сигналы не блокируются */

20 Sigemptyset(&newmask);

21 Sigemptyset(&oldmask);

22 Sigaddset(&newmask, SIGUSRl);

23 /* установка обработчика, включение уведомления */

24 Signal(SIGUSRl, sig usrl):

25 sigev.sigev notify = SIGEV SIGNAL:

26 sigev. si gev signo = SIGUSRl:

27 Mq notify(mqd, &sigev):

28 for ( ; : ) {

29 Sigprocmask(SIG BLOCK, &newmask, &oldmask): /* блокируем SIGUSRl */

30 while (mqflag =- 0)

31 sigsuspend(&zeromask);

32 mqflag -0: /* сброс флага */

33 Mq notify(mqd, &sigev): /* перерегистрируемся */

34 n = Mq receive(mqd, buff, attr.mq msgsize, NULL):

35 printf( read ld bytes\n , (long) n):

36 Sigprocmask(SIG UNBLOCK, &newmask, NULL): /* разблокируем SIGUSRl */

37 }

38 exit(O):

39 }

40 static void

41 sig usrl(int signo)

42 {

43 mqf1ag = 1:

44 return:

45 )



Ожидание установки флага обработчиком

28-32 Мы вызываем sigprocmask, чтобы заблокировать SIGUSRl, сохраняя текущую маску сигналов в oldmask. Затем мы в цикле проверяем значение глобального флага mqflag, ожидая, когда обработчик сигнала установит его в ненулевое значение. Пока значение этого флага равно нулю, мы вызываем sigsuspend, что автоматически приостанавливает вызывающий поток и устанавливает его маску в zeromask (сигналы не блокируются). Раздел 10.16 [21] рассказывает о функции sigsuspend более подробно. Также там объясняются причины, по которым мы должны проверять значение переменной mqf 1 ад только при заблокированном сигнале SIGUSR1. Каждый раз при выходе из sigsuspend сигнал SIGUSRl блокируется.

Перерегистрация и считывание сообщения

33-36 Когда флаг mqflag принимает ненулевое значение, мы регистрируемся на получение уведомления заново и считываем сообщение из очереди. Затем мы разблокируем сигнал SIGUSRl и возвращаемся к началу цикла.

Мы уже говорили, что в этой версии программы также присутствует ошибка. Посмотрим, что произойдет, если в очередь попадут два сообщения, прежде чем будет считано первое из них. Мы можем имитировать это, добавив sleep перед вызовом mq noti fy. Проблема тут в том, что уведомление отсылается только в том случае, когда сообщение помещается в пустую очередь. Если в очередь поступают два сообщения, прежде чем первое будет считано, то отсылается только одно уведомление. Тогда мы считываем первое сообщение и вызываем sigsuspend, ожидая поступления еще одного. А в это время в очереди уже имеется сообщение, которое мы должны прочитать, но которое мы никогда не прочтем.

Пример: уведомление сигналом с отключением блокировки

Исправить описанную выше ошибку можно, отключив блокировку операции считывания сообщений. Листинг 5.10 содержит измененную версию программы из листинга 5.9. Новая программа считывает сообщения в неблокируемом режиме.

Листинг 5.10. /1спользование уведомления с помощью сигнала для считывания сообщения из очереди сообщений Posix

pxmsg/mqnotifysig3.c

1 #include unpipcli

2 volatile sig atoniic t mqflag; /* ненулевое значение устанавливается

обработчиком сигнала */

3 static void sig usrl(int):

4 int

5 mainCint argc. cliar **argv)

7 mqd t mqd;

8 void *buff:

9 ssize t n:

10 sigset t zeromask. newmask, oldmask:

11 struct mq attr attr;



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.
Копирование материалов разрешено исключительно при условии цититирования.