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

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

23 mqhdr->niqh picl = 0; /* снятие вызвавшего процесса с регистрации */

24 } /* если вызвавший процесс не

зарегистрирован - 61К */

25 } else {

26 if (mqhdr->mqh pid != 0) {

27 if (kill(mqhdr->mqh pid, 0) != -1 errno != ESRCH) {

28 errno - EBUSY;

29 goto err;

30 }

31 }

32 mqhdr->mqhj)1d = pid;

33 mqhdr->mqh event = *notification;

34 }

35 pthread mutex unlock(&mqhdr->mqh lock);

36 return(O);

37 err:

38 pthread mutex unlock(&mqhdr->mqh lock);

39 return(-l);

40 }

Снятие процесса с регистрации

20-24 Если второй аргумент представляет собой нулевой указатель, вызвавший процесс снимается с регистрации. Если он не зарегистрирован, никакой ошибки не возвращается.

Регистрация вызвавшего процесса

25-34 Если какой-либо процесс уже зарегистрирован, мы проверяем, существует ли он, отправкой ему сигнала с кодом О (называемого нулевым сигналом - null signal). Это обычная проверка на возможность ошибки, на самом деле при этом никакого сигнала процессу не отправляется, но при его отсутствии возвращается ошибка с кодом ESRCH. Если какой-либо процесс уже зарегистрирован на уведомление, функция возвращает ошибку EBUSY. В противном случае сохраняется идентификатор процесса вместе с его структурой sigevent.

ПРИМЕЧАНИЕ

Наш метод проверки существования вызвавшего процесса не идеален. Процесс мог завершить работу, а его идентификатор мог быть использован другим процессом.

Функция mq send

в листинге 5,25 приведен текст первой половины нашей функции mq send.

Инициализация

14-29 Мы ползпаем указатели на используемые структуры и блокируем взаимное исключение для данной очереди. Проверяем, не превышает ли размер сообщения максимально допустимый для данной очереди.

Проверка очереди на пустоту и отправка уведомления

30-38 Если мы помещаем первое сообщение в пустую очередь, нужно проверить, не зарегистрирован ли какой-нибудь процесс на уведомление об этом событии и нет



ПРИМЕЧАНИЕ

Вызов sigqueue для отправки сигнала приводит к передаче сигнала SI QUEUE обработчику сигнала в структуре типа siginfo t (раздел 5.7), что неправильно. Отправка правильного значения si code (а именно SI MESGQ) из пользовательского процесса осуществляется в зависимости от реализации. Нас. 433 стандарта IEEE 1996 [8] отмечается, что для отправки этого сигнала из пользовательской библиотеки необходимо воспользоваться скрытым интерфейсом механизма отправки сигналов.

Проверка заполненности очереди

39-48 Если очередь переполнена и установлен флаг 0 NONBLOCK, мы возвращаем ошибку с кодом EAGAIN. В противном случае мы ожидаем сигнала по условной переменной mqh wai t, который, как мы увидим, отправляется функцией mq recei ve при считывании сообщения из переполненной очереди.

ПРИМЕЧАНИЕ -

Наша реализация упрощает ситуацию с возвращением ошибки EINTR при прерывании вызова mq send сигналом, перехватываемым вызвавшим процессом. Проблема в том, что функция pthread cond wait не возвращает ошибки при возврате из обработчика сигнала: она может вернуть либо О (что рассматривается как ложное пробуждение), либо вообще не завершить работу. Все эти проблемы можно обойти, но это непросто.

В листинге 5.26 приведена вторая половина функции mq send. К моменту ее выполнения мы уже знаем о наличии в очереди свободного места для нашего сообщения.

Листинг 5.25. Функция mq send: первая половина

niy pxmsg mmap/mq sencl. с

1 #inclucle unpipc.h

2 #inclucle mqueue.h

3 int

4 mymq sencl(mymqcl t mqd, const char *ptr. size t len, unsigned int prio)

6 int n:

7 long index, freeindex;

8 int8 t *mptr;

9 struct sigevent *sigev;

10 struct mymq hdr *mqhdr;

11 struct mymq attr *attr;

12 struct rnymsg hdr *msghdr, *nmsghdr, *pmsghdr;

13 struct mymq info *mqinfo;

14 mqinfo = mqd: продолжение

ли потоков, заблокированных в вызове mq recei ve. Для проверки второго условия мы воспользуемся сохраняемым функцией niq recei ve счетчиком mqh nwai t, содержащим количество потоков, заблокированных в вызове niq recei ve. Если этот счетчик имеет ненулевое значение, мы не отправляем уведомление зарегистрированному процессу. Для отправки сигнала SIGE\/ SIGNAL используется функция sigqueue. Затем процесс снимается с регистрации.



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

15 if (mqinfo->niqi niagic != MQI MAGIC) {

16 еггпо = EBADF-,

17 return(-l);

18 }

19 mqhdr = mqinfo->mqi hdr; /* указатель типа struct */

20 mptr = (int8 t *) mqhdr; /* указатель на байт */

21 attr = &mqhdr->mqh attr:

22 if ( (n = pthread mutexJock(&mqhdr->mqhJock)) != 0) {

23 errno = n;

24 return(-l);

25 }

26 if (len > attr->mq msgsize) {

27 errno - EMSGSIZE;

28 goto err;

29 }

30 if (attr->mq curmsgs == 0) {

31 if (mqhdr->mqh pid != 0 && mqhdr->mqh nwait = 0) {

32 sigev = &mqhdr->mqh event;

33 if (sigev->sigev notify == SIGEV SIGNAL) {

34 sigqueue(mqhdr->mqh pid, sigev->sigev signo,

35 sigev->slgev value);

36 }

37 mqhdr->mqh pid = 0; /* снятие с регистрации */

38 }

39 } else if (attr->mq cunnsgs >= attr->mq maxmsg) {

40 /* 4queue is full */

41 if (mqinfo->mqi flags & OJONBLOCK) { 32 errno = EAGAIN:

43 goto err;

44 }

45 /* ожидание освобождения места в очереди */

46 while (attr->mq curmsgs >= attr->mq maxmsg)

47 pthread cond wait(&mqhdr->mqh wait, &mqhdr->mqh lock):

48 }

Листинг 5.26. Функция mq send: вторая половина

my pxmsg mmap/mq send.с

49 /* nmsghdr будет указывать на новое сообщение*/

50 if ( (freeindex = mqhdr->mqh free) == 0)

51 err dump( mymq send: curmsgs = Id; free = 0 , attr->mq curmsgs);

52 nmsghdr = (struct mymsg hdr *) &mptr[freeindex]:

53 nmsghdr->msg prio = prio:

54 nmsghdr->msg len = len;

55 memcpy(nmsghdr + 1, ptr, len); /* копирование сообщения в очередь */

56 mqhdr->mqh free = nmsghdr->msg next: /* новое начало списка пустых сообщений */

57 /* поиск места в списке для нового сообщения */

58 index = mqhdr->mqh head;

59 pmsghdr = (struct mymsg hdr *) &(mqhdr->mqh head):

60 while (index != 0) {

61 msghdr = (struct mymsg hdr *) &mptr[index];

62 if (prio > msghdr->msg prio) {

63 nmsghdr->msg next = index;

64 pmsghdr->msg next = freeindex:



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