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

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

28 struct niymq hclr *mqi hclr; /* начало отображаемого фа11ла */

29 long mqi niagic: /* магическое значение после инициализации */

30 int mqi flags: /* флаги для данного процесса */

31 }:

32 #clefine MQI MAGIC 0x98765432

33 /* размер сообщения округляется для подгонки */

34 #define MSGSIZE(i) ((((i) + sizeof(long)-l) / sizeof(long)) * sizeof(long))

Структура nriq hdr

8-18 Эта структура хранится в самом начале отображаемого файла и содержит всю информацию об очереди. Поле mq f 1 ags структуры mqii attr не используется, поскольку флаги (единственный определенный флаг используется для отключения блокировки) должны обрабатываться для каждого открывающего очередь процесса в отдельности, а не для очереди в целом. Поэтому флаги хранятся в структуре mq i nf0. О прочих полях этой структуры мы будем говорить в связи с их использованием различными функциями.

Обратите внимание, что все переменные, называемые нами индексными (поля этой структуры mqii iiead и mqli f гее, а также поле msg next следующей структуры), содержат индексы байтов относительно начала отображаемого в память файла. Например, размер структуры mq lidr в системе Solaris 2.6 - 96 байт, поэтому индекс первого сообщения, располагающегося сразу за заголовком, имеет значение 96. Каждое сообщение на рис. 5.2 занимает 20 байт (12 байт на структуру msg iidr и 8 байт на данные), поэтому индексы следующих трех сообщений имеют значения 116, 136 и 156, а размер отображаемого в память файла - 176 байт. Индексы используются для обработки двух связных списков, хранящихся в этом файле: в одном из списков (mqii iiead) хранятся все сообщения, имеющиеся в данный момент в очереди, а в другом (mqli f гее) - все незаполненные сообщения. Мы не можем использовать настоящие указатели на области памяти (адреса) при работе со списком, поскольку отображаемый файл может находиться в произвольной области памяти для каждого из процессов, работающих с ним (как показано в листинге 13.5).

Структура msg hdr

19-25 Эта структура располагается в начале каждого сообщения в отображаемом файле. Любое сообщение может принадлежать либо к списку заполненных, либо к списку свободных сообщений, и поле msgnext содержит индекс следующего сообщения в этом списке (или О, если сообщение является в этом списке последним). Переменная msg len хранит реальную длину данных в сообщении, которая в нашем примере с рис. 5.2 может иметь значение от О до 7 байт включительно. В переменную msg prio отправителем помещается значение приоритета сообщения.

Структура mqjnfo

26-32 Экземпляр такой структзфы динамически создается функцией mq open при открытии очереди и удаляется mq close. Поле mqi lidr указывает на отображае-



мый файл (адрес начала файла возвращается шар). Указатель на эту структуру имеет основной в нашей реализации тип mqd t, он принимает значение, возвращаемое mq open.

Поле mqi magi с принимает значение MQI MAGIC в момент инициализации структуры. Это значение проверяется всеми функциями, которым передается указатель типа mqd t, что дает им возможность удостовериться, что указатель действительно указывает на структуру типа mq i nf о. niqi f 1 ags содержит флаг отключения блокировки для открывшего очередь процесса.

Макрос MSGSIZE

33-34 В целях выравнивания содержимого файла (alignment) мы располагаем начало каждого сообщения так, чтобы его индекс был кратен размеру длинного целого. Следовательно, если максимальный размер сообщения не допускает такого выравнивания, мы добавляем к нему от 1 до 3 байт, как показано на рис. 5.2. При этом предполагается, что размер длинного целого - 4 байт (что верно для Solaris 2.6). Если размер длинного целого 8 байт (в Digital Unix 4.0В), нам придется добавлять к каждому сообщению от 1 до 7 байт.

Функция mq open

В листинге 5.17 приведен текст первой части функции mq open, создающей новую очередь сообщений или открывающей существующую.

Листинг 5.17. Функция mq open: первая часть

niy pxmsg mmap/mq open. с

1 #inclucle unpipc.h

2 #inclucle mqueue.h

3 #inclucle <stclarg.h>

4 Idefine MAXJRIES 10

5 struct niymq attr defattr =

6 { 0. 128. 1024. 0 }:

7 rnymqd t

8 niymq open(const char *pathnanie. int oflag. ...)

10 int 1. fd. nonblock. created. save errno;

11 long msgsize. filesize. index;

12 vajist ap;

13 mode t mode;

14 int8 t *mptr;

15 struct stat statbuff;

16 struct mymq hdr *mqhdr;

17 struct rnymsg hdr *msghdr;

18 struct mymq attr *attr:

19 struct rnymqjnfo *mqinfo;

20 pthread mutexattr t mattr;

21 pthread condattr t cattr;

22 created - 0;

23 nonblock = oflag & OJONBLOCK: продолжение



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

24 oflag &= -0 NONBLOCK:

25 mptr = (int8 t *) MAPJAILED:

26 mqinfo = NULL:

27 again:

28 if (oflag & 0 CREAT) {

29 va start(ap. oflag): /* ap инициализируется последним аргументом */

30 mode = va arg(ap. va mode t) & -SJXUSR;

31 attr = va arg(ap. struct mymq attr *):

32 va end(ap):

33 /* открытие с установкой бита user-execute */

34 fd = open (pathname, oflag OJXCL 0 RDWR. mode ) S IXUSR):

35 if (fd < 0) {

36 if (errno == EEXIST && (oflag & OJXCL) = 0)

37 goto exists: /* уже существует. OK */

38 else

39 return((mymqd t) -1):

40 }

41 created = 1:

42 /* при создании файла он инициализируется */

43 if (attr =- NULL)

44 attr - &defattr:

45 else {

46 if (attr->mq maxmsg <= 0 attr->mq msgsize <= 0) {

47 errno = EINVAL;

48 goto err:

49 }

50 }

Обработка списка аргументов переменного размера

29-32 Функция может быть вызвана либо с двумя, либо с четырьмя аргументами в зависимости от того, указан ли флаг 0 CREAT. Если флаг указан, третий аргумент имеет тип mode t, а это простой системный тип, являющийся одним из целых типов. При этом мы столкнемся с проблемой в BSD/OS, где этот тип данных определен как unsigned siiort (16 бит). Поскольку целое в этой реализации занимает 32 бита, компилятор С увеличивает аргумент этого типа с 16 до 32 бит, потому что все короткие целые в списке аргументов увеличиваются до обычных целых. Но если мы укажем mode t при вызове va arg, он пропустит 16 бит аргумента в стеке, если этот аргумент был увеличен до 32 бит. Следовательно, мы должны определить свой собственный тип данных, va mode t, который будет целым в BSD/OS и типом model в других системах. Эту проблему с переносимостью решают приведенные ниже строки нашего заголовка unpi рс. ii (листинг В. 1):

#ifdef bsdi #define va mode t int #el se

#define va mode t mode t #endif

30 Мы сбрасываем бит user-execute (S IXUSR) в переменной mode по причинам, которые будут вскоре раскрыты.

Создание новой очереди сообщений

33-34 Создается обычный файл с именем, указанным при вызове функции, и устанавливается бит user-execute.



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