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

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

Таблица 2.1. Функции Posix IPC

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

Семафоры

Общая память

Заголовочный файл

<mqueue.h>

<semaphore.h>

<sys/mman.h>

Функции для создания,

mq open

sem open

shm open

открытия и удаления

mq cIose

sem close

shm unlink

mq unlink

sem unlink

sem init

sem destroy

Операции управления

mq getattr

ftruncate

mq setattr

fstat

Операции IPC

mq send

sem wait

mmap

mq receive

sem trywait

munmap

mq notify

sem post

sem getvalue

Таким образом, для лучшей переносимости имена должны начинаться со слэша (/) и не содержать в себе дополнительных слэшей. К сожалению, эти правила, в свою очередь, приводят к проблемам с переносимостью.

В системе Solaris 2.6 требуется наличие начального слэша и запрещается использование дополнительных. Для очереди сообщений, например, при этом создаются три файла в каталоге /tmp, причем имена этих файлов начинаются с .MQ. Например, если аргумент функции iiK open имеет вид /queue. 1234, то созданные файлы будут иметь имена /tnop/ .MQDqueue. 1234, /tmp/ .MQLqueue. 1234 и /tnop/ .MQPqueue. 1234. В то же время в системе Digital Unix 4.0В просто создается файл с указанным при вызове функции именем.

Проблема с переносимостью возникает при указании имени с единственным слэшем в начале; при этом нам нужно иметь разрешение на запись в корневой каталог. Например, очередь с именем /tmp. 1234 допустима стандартом Posix и не вызовет проблем в системе Solaris, но в Digital Unix возникнет ошибка создания файла, если разрешения на запись в корневой каталогу программы нет. Если мы укажем имя /tmp/test. 1234, проблемы в Digital Unix и аналогичных системах, создающих файл с указанным именем, пропадут (предполагается существование каталога /tmp и наличие у программы разрешения на запись в него, что обычно для большинства систем Unix), однако в Solaris использование этого имени будет невозможно.

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

ПРИМЕЧАНИЕ---

Разработчики стремились разрешить использование очередей сообщений, семафоров и разделяемой памяти для существующих ядер Unix и в независимых бездисковых системах. Это тот случай, когда стандарт получается чересчур общим и в результате вызывает проблемы с переносимостью. В отношении Posix это называется как стандарт становится нестандартным .

Стандарт Posix. 1 определяет три макроса: S TYPEISMQ(iM/)



S TYPEISSEM(iM/) S TYPEISSHM(iM/)

которые принимают единственный аргумент - указатель на структуру типа stat, содержимое которой задается функциями fstat, 1 stat и stat. Эти три макроса возвращают ненулевое значение, если указанный объект IPC (очередь сообщений, семафор или сегмент разделяемой памяти) реализован как особый вид файла и структура stat ссылается на этот тип. В противном случае макрос возвращает 0.

ПРИМЕЧАНИЕ-

К сожалению, проку от этих макросов мало, потому что нет никаких гарантий, что эти типы IPC реализованы как отдельные виды файлов. Например, в Solaris 2.6 все три макроса всегда возвращают 0.

Все прочие макросы, используемые для проверки типа файла, имеют имена, начинающиеся с S IS, и принимают всегда единственный аргумент: поле st mode структуры stat. Поскольку макросы, используемые для проверки типа IPC, принимают аргументы другого типа, их имена начинаются с S TYPEIS.

Функция pxjpc name

Существует и другое решение упомянутой проблемы с переносимостью. Можно определить нашу собственную функцию px i pc name, которая добавляет требуемый каталог в качестве префикса к имени Posix IPC.

finclude unpipc.h

char *px ipc name(const char *name);

/* Возвращает указатель при успешном завершении. NULL при возникновении ошибки */

ПРИМЕЧАНИЕ-

Так выглядят листинги наших собственных функций, то есть функций, не являющихся стандартными системными. Обычно включается заголовочный файл unpipc.h (листинг В.1).

Аргумент пате (имя) не должен содержать слэшей. Тогда, например, при вызове px ipc name( testl ) будет возвращен указатель на строку /testl в Solaris 2.6 или на строку /tmp/testl в Digital Unix 4.0В. Память для возвращаемой строки выделяется динамически и освобождается вызовом free. Можно установить произвольное значение переменной окружения PX IPC NAME, чтобы задать другой каталог по умолчанию.

В листинге 2.1 приведен наш вариант реализации этой функции.

ПРИМЕЧАНИЕ-

Возможно, в этом листинге вы в первый раз встретитесь с функцией snprintf. Значительная часть существующих программ используют вместо нее функцию sprintf, однако последняя не производит проверки переполнения приемного буфера. В отличие от нее snprintf получает в качестве второго аргумента размер приемного буфера и впоследствии предотвращает его переполнение. Умышленное переполнение буфера программы, использующей sprintf, в течение многих лет использовалось хакерами для взлома систем.

Все исходные тексты, опубликованные в aroii книге, вы можете найти по адресу littp: www.piter.com/ download.



Функция snprintf еще не является частью стандарта ANSI С, но планируется ее включение в обновленный стандарт, называющийся С9Х. Тем не менее многие производители включают ее в стандартную библиотеку С. Везде в тексте мы используем функцию snprintf в нашем собственном варианте, обеспечивающем вызов sprintf, если в системной библиотеке функция snprinft отсутствует.

Листинг 2.1. Функция pxjpc name в нашей реализации.

lib/px ipc name.c 1 finclude unpipc.h

2 3 4 5

8 9 10 11 12 13 14 15 16 17 18

char *

pxjpc name(const char *name) {

char *dir. *dst. *slash:

if ( (dst - malloc(PATH MAX)) return(NULL):

NULL)

/* есть возможность задать другое имя каталога с помощью переменной окружения */ if ( (dir - getenvCPX IPCJAME )) -= NULL) { #ifdef POSIX IPC PREFIX

dir - POSIX IPC PREFIX; /* из config.h */

#else

dir = /tmp/ ; /* no умолчанию */

#endif }

/* имя каталога должнозаканчиваться символом / */ slash - (dir[strlen(dir) - 1] 7) ? : / ; snprintfCdst, PATH MAX, %s%s%s , dir. slash, name);

return(dst);

/* для хвобождения этого указателя можно вызвать freeО */

2.3. Создание и открытие каналов IPC

Все три функции, используемые для создания или открытия объектов IPC: 1Щ ореп, seffl open и slim open, - принимают специальный флаг oflag в качестве второго аргумента. Он определяет параметры открытия запрашиваемого объекта аналогично второму аргументу стандартной функции open. Все константы, из которых можно формировать этот аргумент, приведены в табл. 2.2.

Таблица 2.2. Константы, используемые при создании и открытии объектов IPC

Описание

mq open

sem.open

shm.open

Только чтение

RDONLY

RDONLY

Только запись

WRONLY

Чтение и запись

RDWR

RDWR

Создать, если ие существует

CREAT

0 CREAT

CREAT

Исключающее создание

EXCL

0 EXCL

EXCL

Без блокировки

NONBLOCK

Сократить (truncate) существ>ющий

TRUNC



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