Литмир - Электронная Библиотека
Содержание  
A
A

Очереди сообщений предоставляют очень легкий и эффективный способ передачи данных между двумя несвязанными процессами. У них есть преимущество по сравнению с именованными каналами, заключающееся в том, что очередь сообщений существует независимо как от отправляющего, так и от принимающего процессов, что устраняет некоторые трудности, возникающие при синхронизации открытия и закрытия именованных каналов.

Очереди сообщений обеспечивают отправку блока данных из одного процесса в другой. Кроме того, каждый блок данных наделяется типом, и принимающий процесс может получать независимо блоки данных, имеющие разные типы. Хорошо и то, что, отправляя сообщения, вы можете почти полностью избежать проблем синхронизации и блокировки, связанных с именованными каналами. Еще лучше то, что вы можете проявить предусмотрительность в отношении неотложных в том или ином смысле сообщений. К недостаткам следует отнести то, что, как и в случае каналов, в системе существует ограничение максимального объема блока данных и максимального объема всех блоков данных во всех очередях.

Наложив эти ограничения, стандарт X/Open не позаботился о способе выяснения их числовых значений за исключением того, что превышение ограничений — достаточное основание для аварийного завершения функций обработки очереди сообщений. В ОС Linux есть два определения:

MSGMAX
и
MSGMNB
, которые задают максимальный объем в байтах отдельного сообщения и максимальный объем очереди соответственно. В других системах эти макросы могут отличаться или просто отсутствовать.

Далее приведены объявления функций для работы с очередями сообщений:

<b>#include &lt;sys/msg.h&gt;</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
.

257
{"b":"285844","o":1}