Чтение онлайн

на главную - закладки

Жанры

UNIX: взаимодействие процессов

Стивенс Уильям Ричард

Шрифт:

■ Имя должно соответствовать существующим требованиям к именам файлов (не превышать в длину РАТНМАХ байтов, включая завершающий символ с кодом 0).

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

■ Интерпретация дополнительных слэшей в имени зависит от реализации.

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

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

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

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

ПРИМЕЧАНИЕ

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

Стандарт Posix.1 определяет три макроса:

S_TYPEISMQ(buf)

S_TYPEISSEM(buf)

S_TYPEISSHM(buf)

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

ПРИМЕЧАНИЕ

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

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

Функция px_ipc_name

Существует и другое решение упомянутой проблемы с переносимостью. Можно определить нашу собственную функцию 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] приведен наш вариант реализации этой функции.

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);

Поделиться:
Популярные книги

Паразиты

дю Морье Дафна
Проза:
современная проза
6.20
рейтинг книги
Паразиты

Хроники Тириса. Книга 3

Маханенко Василий Михайлович
3. Хроники Тириса
Фантастика:
боевая фантастика
космическая фантастика
фантастика: прочее
5.00
рейтинг книги
Хроники Тириса. Книга 3

Камень. Книга шестая

Минин Станислав
6. Камень
Фантастика:
боевая фантастика
7.64
рейтинг книги
Камень. Книга шестая

Загадка башни

Коган Мстислав Константинович
9. Игра не для слабых
Фантастика:
рпг
фэнтези
попаданцы
5.00
рейтинг книги
Загадка башни

Инкарнатор

Прокофьев Роман Юрьевич
1. Стеллар
Фантастика:
боевая фантастика
рпг
7.30
рейтинг книги
Инкарнатор

Юнлинг

Метельский Николай Александрович
Фантастика:
героическая фантастика
космическая фантастика
попаданцы
8.35
рейтинг книги
Юнлинг

Вернувшийся: Первые шаги. Том II

Vector
2. Вернувшийся
Фантастика:
боевая фантастика
космическая фантастика
рпг
5.00
рейтинг книги
Вернувшийся: Первые шаги. Том II

Эпоха Опустошителя. Том I

Павлов Вел
1. Вечное Ристалище
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Эпоха Опустошителя. Том I

Долг

Кораблев Родион
7. Другая сторона
Фантастика:
боевая фантастика
5.56
рейтинг книги
Долг

Инженер Петра Великого 3

Гросов Виктор
3. Инженер Петра Великого
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Инженер Петра Великого 3

An ordinary sex life

Астердис
Любовные романы:
современные любовные романы
love action
5.00
рейтинг книги
An ordinary sex life

Самые знаменитые произведения писателя в одном томе

Брэдбери Рэй Дуглас
Фантастика:
фантастика: прочее
4.00
рейтинг книги
Самые знаменитые произведения писателя в одном томе

Гримуар темного лорда II

Грехов Тимофей
2. Гримуар темного лорда
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Гримуар темного лорда II

Академия

Щепетнов Евгений Владимирович
3. Петр Синельников
Фантастика:
фэнтези
6.20
рейтинг книги
Академия