Очереди сообщений предоставляют очень легкий и эффективный способ передачи данных между двумя несвязанными процессами. У них есть преимущество по сравнению с именованными каналами, заключающееся в том, что очередь сообщений существует независимо как от отправляющего, так и от принимающего процессов, что устраняет некоторые трудности, возникающие при синхронизации открытия и закрытия именованных каналов.
Очереди сообщений обеспечивают отправку блока данных из одного процесса в другой. Кроме того, каждый блок данных наделяется типом, и принимающий процесс может получать независимо блоки данных, имеющие разные типы. Хорошо и то, что, отправляя сообщения, вы можете почти полностью избежать проблем синхронизации и блокировки, связанных с именованными каналами. Еще лучше то, что вы можете проявить предусмотрительность в отношении неотложных в том или ином смысле сообщений. К недостаткам следует отнести то, что, как и в случае каналов, в системе существует ограничение максимального объема блока данных и максимального объема всех блоков данных во всех очередях.
Наложив эти ограничения, стандарт X/Open не позаботился о способе выяснения их числовых значений за исключением того, что превышение ограничений — достаточное основание для аварийного завершения функций обработки очереди сообщений. В ОС Linux есть два определения: MSGMAX и MSGMNB, которые задают максимальный объем в байтах отдельного сообщения и максимальный объем очереди соответственно. В других системах эти макросы могут отличаться или просто отсутствовать.
Далее приведены объявления функций для работы с очередями сообщений:
<b>#include <sys/msg.h></b>
<b>int msgctl(int msqid, int cmd, struct msqid_ds *buf);</b>
<b>int msgget(key_t key, int msgflg);</b>
<b>int msgrcv(int msqid, void *msg_ptr, size_t msg_sz, long int msgtype, int msgflg);</b>
<b>int msgsnd(int msqid, const void *msg_ptr, size_t msg_sz, int msgflg);</b>
Как и в случае семафоров или совместно используемой памяти, заголовочные файлы sys/types.h и sys/ipc.h обычно автоматически включаются заголовочным файлом msg.h.
msgget
Очередь сообщений создается и предоставляет к себе доступ с помощью функции msgget:
<b>int msgget(key_t key, int msgflg);</b>
Программа должна предоставить значение параметра key, которое, как и в других средствах IPC, задает имя конкретной очереди сообщений. С помощью специального значения IPC_PRIVATE создается скрытая или частная очередь, которая теоретически доступна только текущему процессу. Как и в случае семафоров и совместно используемой памяти, в некоторых системах Linux такая очередь может не быть частной. Поскольку от скрытой или частной очереди очень мало пользы, это не слишком важная проблема. Как и раньше, второй параметр msgflg состоит из девяти флагов прав доступа. Для создания новой очереди сообщений специальный бит со значением IPC_CREAT должен быть объединен с правами доступа поразрядной операцией OR. Не считается ошибкой установка флага IPC_CREAT и задание ключа уже существующей очереди сообщений. Если очередь уже есть, флаг IPC_CREAT безмолвно игнорируется.
Функция msgget вернет положительное число, идентификатор очереди; в случае успешного завершения и -1 в случае сбоя.
msgsnd
Функция msgsnd позволяет добавить сообщение в очередь сообщений:
<b>int msgsnd(int msqid, const void *msg_ptr, size_t msg_sz, int msgflg);</b>
Структура сообщения ограничена двумя способами. Во-первых, она должна быть меньше системного ограничения, и во-вторых, она должна начинаться с элемента типа long int, который будет использован как тип сообщения в получающей функции. Если вы применяете сообщения, лучше всего определить структуру сообщения следующим образом.
<b>struct my_message {</b>
<b> long int message_type;</b>
<b> /* Данные, которые вы собираетесь передавать */</b>
<b>}</b>
Поскольку элемент message_type используется при получении сообщения, вы не можете его просто игнорировать. Вы должны включить его в вашу структуру данных, и будет разумно инициализировать его с помощью известного значения.
Первый параметр msqid — идентификатор очереди сообщений, возвращаемый функцией msgget.
Второй параметр msg_ptr — указатель на отправляемое сообщение, которое должно начинаться с элемента типа long int, как описывалось ранее.
Третий параметр msg_sz — объем сообщения, на которое указывает msg_ptr. Этот объем не должен включать элемент типа long int, содержащий тип сообщения.
Четвертый параметр msgflg управляет действиями, предпринимаемыми при заполнении текущей очереди сообщений или достижении общесистемного ограничения для очередей сообщений. Если в параметре msgflg установлен флаг IPC_NOWAIT, функция вернет управление немедленно без отправки сообщения и возвращаемое значение будет равно -1. Если в параметре msgflg флаг IPC_NOWAIT сброшен, процесс отправки будет приостановлен в ожидании освобождения доступного объема в очереди.
В случае успеха функция вернет 0, а в случае аварийного завершения — -1. Если вызов был успешен, копия данных сообщения принимается и помещается в очередь сообщений.
msgrcv
Функция msgrcv извлекает сообщения из очереди сообщений:
<b>int msgrcv(int msqid, void *msg_ptr, size_t msg_sz, long int msgtype, int msgflg);</b>
Первый параметр msqid — идентификатор очереди сообщений, возвращенный функцией msgget.
Второй параметр msg_ptr — указатель на получаемое сообщение, которое должно начинаться с элемента типа long int, как описывалось ранее в функции msgsnd.
Третий параметр msg_sz — размер сообщения, на которое указывает msg_ptr, без элемента типа long int, содержащего тип сообщения.
Четвертый параметр msgtype типа long int позволяет реализовать простую форму приоритетного получения. Если значение msgtype равно 0, извлекается первое доступное сообщение в очереди. Если значение параметра больше нуля, извлекается первое сообщение с таким же типом сообщения. Если оно меньше нуля, извлекается первое сообщение с таким же типом сообщения или со значением, по абсолютной величине меньшим, чем msgtype.