ПРИМЕЧАНИЕ
К сожалению, проку от этих макросов мало, потому что нет никаких гарантий, что эти типы IPC реализованы как отдельные виды файлов. Например, в Solaris 2.6 все три макроса всегда возвращают 0.
Все прочие макросы, используемые для проверки типа файла, имеют имена, начинающиеся с S_IS, и принимают всегда единственный аргумент: поле st_mode структуры stat. Поскольку макросы, используемые для проверки типа IPC, принимают аргументы другого типа, их имена начинаются с S_TYPEIS.
Существует и другое решение упомянутой проблемы с переносимостью. Можно определить нашу собственную функцию px_ipc_name, которая добавляет требуемый каталог в качестве префикса к имени Posix IPC.
#include "unpipc.h"
char *px_ipc_name(const char *name );
/* Возвращает указатель при успешном завершении, NULL при возникновении ошибки */
ПРИМЕЧАНИЕ
Так выглядят листинги наших собственных функций, то есть функций, не являющихся стандартными системными. Обычно включается заголовочный файл unpipc.h (листинг B.1).
Аргумент пате (имя) не должен содержать слэшей. Тогда, например, при вызове px_ipc_name("test1") будет возвращен указатель на строку /test1 в Solaris 2.6 или на строку /tmp/test1 в Digital Unix 4.0B. Память для возвращаемой строки выделяется динамически и освобождается вызовом free. Можно установить произвольное значение переменной окружения PX_IPC_NAME, чтобы задать другой каталог по умолчанию.
В листинге 2.1 [1] Все исходные тексты, опубликованные в этой книге, вы можете найти по адресу http://www.piter.com/download.
приведен наш вариант реализации этой функции.
ПРИМЕЧАНИЕ
Возможно, в этом листинге вы в первый раз встретитесь с функцией snprintf. Значительная часть существующих программ используют вместо нее функцию sprintf, однако последняя не производит проверки переполнения приемного буфера. В отличие от нее snprintf получает в качестве второго аргумента размер приемного буфера и впоследствии предотвращает его переполнение. Умышленное переполнение буфера программы, использующей sprintf, в течение многих лет использовалось хакерами для взлома систем.
Функция snprintf еще не является частью стандарта ANSI С, но планируется ее включение в обновленный стандарт, называющийся С9Х. Тем не менее многие производители включают ее в стандартную библиотеку С. Везде в тексте мы используем функцию snprintf в нашем собственном варианте, обеспечивающем вызов sprintf, если в системной библиотеке функция snprinft отсутствует.
Листинг 2.1. Функция px_ipc_name в нашей реализации.
//lib/px_ipc_name.c
1 #include "unpipc.h"
2 char *
3 px_ipc_name(const char *name)
4 {
5 char *dir, *dst, *slash;
6 if ((dst = malloc(РАТН_МАХ)) == NULL)
7 return(NULL);
8 /* есть возможность задать другое имя каталога с помощью переменной окружения */
9 if ((dir = getenv("PX IPC_NAME")) == NULL) {
10 #ifdef POSIX_IPC_PREFIX
11 dir = POSIX_IPC_PREFIX; /* из "config.h" */
12 #else
13 dir = "/tmp/"; /* по умолчанию */
14 #endif
15 }
16 /* имя каталога должно заканчиваться символом '/' */
17 slash = (dir[strlen(dir) – 1] == '/') ? "" : "/";
18 snprintf(dst, PATH_MAX, "%s%s%s", dir, slash, name);
19 return(dst); /* для освобождения этого указателя можно вызвать free() */
20 }
2.3. Создание и открытие каналов IPC
Все три функции, используемые для создания или открытия объектов IPC: mq_open, sem_open и shm_open, — принимают специальный флаг oflag в качестве второго аргумента. Он определяет параметры открытия запрашиваемого объекта аналогично второму аргументу стандартной функции open. Все константы, из которых можно формировать этот аргумент, приведены в табл. 2.2.
Таблица 2.2. Константы, используемые при создании и открытии объектов IPC
Описание |
mq_open |
sem_open |
shm_open |
Только чтение |
О_RDONLY |
|
О_RDONLY |
Только запись |
О_WRONLY |
|
|
Чтение и запись |
О_RDWR |
|
О_RDWR |
Создать, если не существует |
О_CREAT |
О_CREAT |
О_CREAT |
Исключающее создание |
О_EXCL |
О_EXCL |
О_EXCL |
Без блокировки |
О_NONBLOCK |
|
|
Сократить (truncate) существующий |
|
|
O_TRUNC |
Первые три строки описывают тип доступа к создаваемому объекту: только чтение, только запись, чтение и запись. Очередь сообщений может быть открыта в любом из трех режимов доступа, тогда как для семафора указание этих констант не требуется (для любой операции с семафором требуется доступ на чтение и запись). Наконец, объект разделяемой памяти не может быть открыт только на запись.
Читать дальше
Конец ознакомительного отрывка
Купить книгу