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

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

Жанры

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

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

Шрифт:

Функция mq_open

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

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

//my_pxmsg._mmap/mq_open. с

1 #include "unpipc.h"

2 #include "mqueue.h"

3 #include <stdarg.h>

4 #define MAX_TRIES 10

5 struct mymq_attr defattr =

6 { 0, 128, 1024, 0 };

7 mymqd_t

8 mymq_open(const char *pathname, int oflag, …)

9 {

10 int i, fd, nonblock, created, save_errno;

11 long msgsize, filesize, index;

12 va_list ap;

13 mode_t mode;

14 int8_t *mptr;

15 struct stat statbuff;

16 struct mymq_hdr *mqhdr;

17 struct mymsg_hdr *msghdr;

18 struct mymq_attr *attr;

19 struct mymq_info *mqinfo;

20 pthread_mutexattr_t mattr;

21 pthread_condattr_t cattr;

22 created = 0;

23 nonblock = oflag & O_NONBLOCK;

24 oflag &= ~O_NONBLOCK;

25 mptr = (int8_t *) MAP_FAILED;

26 mqinfo = NULL;

27 again:

28 if (oflag & O_CREAT) {

29 va_start(ap, oflag); /* ар инициализируется последним аргументом */

30 mode = va_arg(ap, va_mode_t) & ~S_IXUSR;

31 attr = va_arg(ap, struct mymq_attr *);

32 va_end(ap);

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

34 fd = open (pathname, oflag | O_EXCL | O_RDWR, mode | S_IXUSR);

35 if (fd < 0) {

36 if (errno == EEXIST && (oflag & O_EXCL) == 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 Функция может быть вызвана либо с двумя, либо с четырьмя аргументами в зависимости от того, указан ли флаг O_CREAT. Если флаг указан, третий аргумент имеет тип mode_t, а это простой системный тип, являющийся одним из целых типов. При этом мы столкнемся с проблемой в BSD/OS, где этот тип данных определен как unsigned short (16 бит). Поскольку целое в этой реализации занимает 32 бита, компилятор С увеличивает аргумент этого типа с 16 до 32 бит, потому что все короткие целые в списке аргументов увеличиваются до обычных целых. Но если мы укажем mode_t при вызове va_arg, он пропустит 16 бит аргумента в стеке, если этот аргумент был увеличен до 32 бит. Следовательно, мы должны определить свой собственный тип данных, va_mode_t, который будет целым в BSD/OS и типом mode_t в других системах. Эту проблему с переносимостью решают приведенные ниже строки нашего заголовка unpipc.h (листинг В.1):

#ifdef __bsdi__

#define va_mode_t int

#else

#define va_mode_t mode_t

#endif

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

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

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

Обработка потенциальной ситуации гонок

35-40 Если бы при указании флага O_CREAT мы просто открыли файл, отобразили его содержимое в память и проинициализировали отображенный файл (как будет описано ниже), у нас возникла бы ситуация гонок. Очередь сообщений инициализируется mq_open только в том случае, если вызывающий процесс указывает флаг O_CREAT и очередь сообщений еще не существует. Это означает, что нам нужно каким-то образом определять, существует она или нет. Для этого при открытии файла для последующего отображения в память мы всегда указываем флаг O_EXCL. Возвращение ошибки EEXIST функцией open является ошибкой для mq_open только в том случае, если при вызове был указан флаг O_EXCL. В противном случае при возвращении функцией open ошибки EEXIST мы делаем вывод, что файл уже существует, и переходим к листингу 5.19, как если бы флаг O_CREAT вовсе не был указан.

Ситуация гонок может возникнуть потому, что использование отображаемого в память файла для реализации очереди сообщений требует двух шагов при инициализации очереди: сначала файл должен быть создан функцией open, а затем его содержимое должно быть проинициализировано. Проблема возникает, если два потока (одного или различных процессов) вызывают mq_open приблизительно одновременно. Один из потоков может создать файл, после чего управление будет передано системой второму потоку, прежде чем первый завершит инициализацию файла. Второй поток обнаружит, что файл уже существует (вызвав open с флагом O_EXCL), и приступит к использованию очереди сообщений.

Мы используем бит user-execute для указания того, был ли проинициализирован файл с очередью сообщений. Этот бит устанавливается только тем потоком, который создает этот файл (флаг O_EXCL позволяет определить этот поток); этот поток инициализирует файл с очередью сообщений, а затем сбрасывает бит user-execute.

Аналогичная ситуация может возникнуть в листингах 10.28 и 10.37.

Проверка атрибутов

42-50 Если при вызове в качестве последнего аргумента передан нулевой указатель, очередь сообщений инициализируется со значениями атрибутов по умолчанию: 128 сообщений в очереди и 1024 байта на сообщение. Если атрибуты указаны явно, мы проверяем, что mq_maxmsg и mq_msgsize имеют положительные значения.

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

Я Гордый часть 7

Машуков Тимур
7. Стальные яйца
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Я Гордый часть 7

Кукловод

Злобин Михаил
2. О чем молчат могилы
Фантастика:
боевая фантастика
8.50
рейтинг книги
Кукловод

Наемный корпус

Вайс Александр
5. Фронтир
Фантастика:
боевая фантастика
космическая фантастика
космоопера
5.00
рейтинг книги
Наемный корпус

Иной. Том 1. Школа на краю пустыни

Amazerak
1. Иной в голове
Фантастика:
боевая фантастика
рпг
аниме
5.75
рейтинг книги
Иной. Том 1. Школа на краю пустыни

Подпольная империя

Ромов Дмитрий
4. Цеховик
Фантастика:
попаданцы
альтернативная история
6.60
рейтинг книги
Подпольная империя

Воплощение Похоти

Некрасов Игорь
1. Воплощение Похоти
Фантастика:
юмористическое фэнтези
попаданцы
рпг
аниме
5.00
рейтинг книги
Воплощение Похоти

Семьи.net (сборник)

Панов Вадим Юрьевич
Фантастика:
социально-философская фантастика
научная фантастика
4.40
рейтинг книги
Семьи.net (сборник)

Последний Паладин. Том 12

Саваровский Роман
12. Путь Паладина
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Последний Паладин. Том 12

Хозяин Теней 4

Петров Максим Николаевич
4. Безбожник
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Хозяин Теней 4

Бастард Императора

Орлов Андрей Юрьевич
1. Бастард Императора
Фантастика:
фэнтези
аниме
5.00
рейтинг книги
Бастард Императора

Мы друг друга не выбирали

Кистяева Марина
1. Мы выбираем...
Любовные романы:
остросюжетные любовные романы
прочие любовные романы
современные любовные романы
5.00
рейтинг книги
Мы друг друга не выбирали

Телохранитель Генсека. Том 2

Алмазный Петр
2. Медведев
Фантастика:
попаданцы
альтернативная история
6.25
рейтинг книги
Телохранитель Генсека. Том 2

Неучтенный элемент. Том 11

NikL
11. Антимаг. Вне системы
Фантастика:
фэнтези
5.00
рейтинг книги
Неучтенный элемент. Том 11

Я – Легенда 2: геном хищника

Гарцевич Евгений Александрович
2. Я - Легенда!
Фантастика:
боевая фантастика
рпг
фантастика: прочее
попаданцы
5.00
рейтинг книги
Я – Легенда 2: геном хищника