Интерфейс, предоставляемый POSIX IPC, во многих отношениях превосходит IPC-интерфейс System V, хотя и уступает ему в плане портируемости на другие системы.
48. Очереди сообщений стандарта POSIX
Эта глава посвящена очередям сообщений стандарта POSIX, позволяющим процессам обмениваться данными в виде отдельных блоков (сообщений). Очереди POSIX-сообщений похожи на аналогичный механизм в System V, но имеют несколько заметных отличий:
• для очередей сообщений POSIX ведется учет ссылок. Очередь, помеченная для удаления, уничтожается только после того, как будет закрыта всеми процессами, которые ее используют;
• POSIX-сообщения имеют приоритет, обеспечивающий строгий порядок передачи (и, следовательно, получения);
• уведомление о доступности POSIX-сообщения в очереди может быть передано асинхронно.
Очереди POSIX-сообщений появились в Linux относительно недавно. Необходимая поддержка была реализована только в ядре версии 2.6.6 (кроме того, требуется библиотека gibc 2.3.4 или новее).
Поддержка очередей сообщений POSIX в ядре является опциональной и настраивается с помощью параметра CONFIG_POSIX_MQUEUE.
Ниже перечислены основные функции программного интерфейса для управления очередями POSIX-сообщений:
• mq_open() — создает новую очередь сообщений или открывает уже существующую, возвращая соответствующий дескриптор, который можно использовать в дальнейшем;
• mq_send() — записывает сообщение в очередь;
• mq_receive() — считывает сообщение из очереди;
• mq_close() — закрывает очередь сообщений, открытую ранее текущим процессом;
• mq_unlink() — удаляет имя очереди сообщений; сама очередь удаляется после того, как будет закрыта всеми процессами.
Назначение функций, перечисленных выше, должно быть понятно из их названий. Интерфейс для работы с очередями POSIX-сообщений обладает двумя специфическими свойствами.
• Каждая очередь сообщений имеет определенный набор атрибутов. Часть из них могут быть установлены во время создания или открытия очереди с помощью вызова mq_open(). Для просмотра и изменения этих атрибутов предусмотрены две функции: mq_getattr() и mq_setattr().
• Функция mq_notify() позволяет процессу зарегистрировать оповещение, которое будет сигнализировать о наличии того или иного сообщения в очереди. Это делается путем доставки сигнала или вызова функции в отдельном потоке.
В данной главе мы рассмотрим функции, применяемые для открытия, закрытия и удаления очередей сообщений.
Функция mq_open() создает новую или открывает существующую очередь сообщений.
#include
#include
#include
mqd_t mq_open(const char *
/* mode_t
Возвращает дескриптор очереди сообщений при успешном завершении или (mqd_t) -1, если произошла ошибка
Аргумент name идентифицирует очередь сообщений и соответствует правилам, приведенным в разделе 47.1.
Аргумент oflag представляет собой битовую маску, управляющую различными аспектами работы функции mq_open(). Значения, которые можно включать в эту маску, собраны в табл. 48.1.
Таблица 48.1. Битовые значения для аргумента oflag функции mq_open()
Флаг — Описание
O_CREAT — Создает очередь, если она еще не существует
O_EXCL — В сочетании с O_CREAT создает очередь с уникальным именем
O_RDONLY — Открывает только для чтения
O_WRONLY — Открывает только для записи
O_RDWR — Открывается для чтения и записи
O_NONBLOCK — Открывает в неблокирующем режиме
Одним из назначений флага oflag является определение того, какая именно операция выполняется — открывается существующая очередь или создается и затем открывается новая. При отсутствии в oflag флага O_CREAT будет создана новая пустая очередь с именем name (при условии, что это имя еще не занято). Если в маске oflag одновременно указаны флаги O_CREAT и O_EXCL, а очередь с заданным именем уже существует, то функция mq_open() завершится неудачей.
Аргумент oflag также определяет тип доступа к очереди сообщений, который получит вызывающий процесс; для этого необходимо указать один из трех флагов: O_RDONLY, O_WRONLY или O_RDWR.
Оставшийся флаг, O_NONBLOCK, делает так, чтобы очередь открывалась в неблокирующем режиме. Если последующий вызов mq_receive() или mq_send() нельзя выполнить без блокировки, то он немедленно завершается ошибкой EAGAIN.
Если функция mq_open() используется для открытия уже существующей очереди сообщений, то ей нужно передать всего два аргумента. Но при указании флага O_CREAT еще два аргумента станут обязательными: mode и attr (если имя name уже занято, то эти два аргумента игнорируются). Они применяются следующим образом.