Scroll to navigation

MSGOP(2) Руководство программиста Linux MSGOP(2)

ИМЯ

msgrcv, msgsnd - операции с сообщениями

ОБЗОР

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,
               int msgflg);

ОПИСАНИЕ

Системные вызовы msgsnd() и msgrcv() используются для отправки и получения сообщений из очереди. Вызывающий процесс должен иметь права на запись в очередь сообщений, чтобы отправлять сообщения и права на чтение для получения сообщений.

Аргумент msgp представляет собой указатель на структуру, определяемую вызывающим как:

struct msgbuf {

long mtype; /* тип сообщения, значение должно быть > 0 */
char mtext[1]; /* данные сообщения */ };

Поле mtext является массивом (или другой структурой), размер которого определяется msgsz — неотрицательным целым значением. Разрешены сообщения нулевой длины (т.е. без поля mtext). Поле mtype должно быть только положительным целым значением. Это значение используется процессом-получателем для выбора сообщения (см. описание msgrcv() далее).

msgsnd()

Системный вызов msgsnd() добавляет копию сообщения, указанного msgp, в очередь сообщений, идентификатор которой задаётся в msqid.

Если в очереди достаточно места, то msgsnd() немедленно сообщает о нормальном завершении работы (размер очереди определяется полем msg_qbytes в связанной с очередью сообщений структуре данных. Во время создания очереди это поле инициализируется MSGMNB байтами, но это ограничение может быть изменено с помощью msgctl(2)). Если в очереди недостаточно пространства, то вызов msgsnd() блокируется до тех пор, пока не появится достаточно места. Если в msgflg указан флаг IPC_NOWAIT, то вызов вместо этого выдаст ошибку EAGAIN.

Заблокированный вызов msgsnd() может завершиться ошибкой если:

  • очередь удалена (в этом случае системный вызов выдаст ошибку, определив errno в значение EIDRM;
  • пойман сигнал; в этом случае системный вызов завершается с ошибкой и присваивает errno значение EINTR; см. signal(7). Вызов msgsnd() никогда не перезапускается автоматически после прерывания обработчиком сигнала, независимо от установки флага SA_RESTART при настройке обработчика сигнала.

Перед успешным завершением структура данных очереди сообщений будет обновлена следующим образом:

Значение msg_lspid устанавливается равным идентификатору вызывающего процесса.
Значение msg_qnum увеличивается на 1.
Значение msg_stime присваивается значение текущего времени.

msgrcv()

Системный вызов msgrcv() удаляет сообщение из очереди, указанной в msqid и помещает его в буфер, указанный в msgp.

Параметр msgsz задаёт максимальный размер (в байтах) элемента mtext структуры, находящейся по адресу, указанному в аргументе msgp. Если длина текста сообщения больше чем msgsz, то поведение зависит от наличия флага MSG_NOERROR в msgflg. Если MSG_NOERROR указан, то текст сообщения будет урезан (а урезанная часть потеряна); иначе сообщение не удаляется из очереди, а системный вызов возвращает -1 и присваивает errno значение E2BIG.

В параметре msgtyp задаётся тип сообщения:

  • Если msgtyp равно нулю, то читается первое сообщение в очереди.
  • Если msgtyp больше нуля, то из очереди читается первое сообщение с типом msgtyp (если только в msgflg не указан MSG_EXCEPT. В этом случае из очереди читается первое сообщение, тип которого не равен msgtyp).
  • Если msgtyp меньше нуля, то из очереди читается первое сообщение со значением, меньшим или равным абсолютному значению msgtyp.

Аргумент msgflg представляет собой битовую маску из комбинации нуля или более следующих флагов:

Немедленный возврат, если в очереди нет сообщений необходимого типа. При этом системный вызов возвращает ошибку, присваивая errno значение ENOMSG.
Используется, если msgtyp больше 0, для чтения первого сообщения в очереди с типом, отличным от msgtyp.
Используется для урезания текста сообщения, если его размер больше msgsz байт.

Если в очереди нет сообщения необходимого типа и в msgflg не указан IPC_NOWAIT, то вызывающий процесс будет заблокирован до тех пор, пока не произойдет одно из следующих событий:

  • В очередь не будет помещено сообщение необходимого типа.
  • Очередь сообщений удалена из системы. В этом случае системный вызов возвращает ошибку и присваивает errno значение EIDRM.
  • Вызывающий процесс не получит сигнал, который должен обработать. В этом случае системный вызов возвращает ошибку и присваивает переменной errno значение EINTR. Вызов msgrcv() никогда не перезапускается автоматически после прерывания обработчиком сигнала, независимо от установки флага SA_RESTART при настройке обработчика сигнала.

Перед успешным завершением структура данных очереди сообщений будет обновлена следующим образом:

Значение msg_lrpid устанавливается равным идентификатору вызывающего процесса.
Значение msg_qnum уменьшается на 1.
Значение msg_rtime становится равным текущему времени.

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ

При ошибке оба вызова возвращают -1, а переменная errno приобретает соответствующее значение. В противном случае msgsnd() возвращает 0, а msgrcv() возвращает количество байтов, скопированных в массив mtext.

ОШИБКИ

Значения errno, устанавливаемые при возникновении ошибок в msgsnd():

Вызывающий процесс не имеет прав записи в очередь сообщений и не имеет мандата CAP_IPC_OWNER.
Сообщение не может быть отправлено, так как размер очереди превысит лимит, равный msg_qbytes, а в параметре msgflg установлен флаг IPC_NOWAIT.
Память с адресом, указанным msgp, недоступна.
Очередь сообщений была удалена.
Процесс ждал свободного места в очереди и получил сигнал, который должен обработать.
Задано неправильное значение msqid, не положительное значение mtype или неправильное значение msgsz (меньше 0, или больше системного лимита, заданного MSGMAX).
Недостаточно памяти в системе для копирования сообщения, указанного msgp.

Значения errno, устанавливаемые при возникновении ошибок в msgrcv():

Длина текста получаемого сообщения больше, чем msgsz, а в поле msgflg не установлен флаг MSG_NOERROR.
Вызывающий процесс не имеет прав на чтение очереди сообщений и не имеет мандата CAP_IPC_OWNER.
Нет сообщения в очереди, а в msgflg указан флаг IPC_NOWAIT.
Память с адресом, указанным msgp, недоступна.
Процесс ждал приёма сообщения, и в это время очередь сообщений была удалена.
Во время ожидания приёма сообщения процесс получил сигнал; см. signal(7).
Неверное значение msgqid или msgsz меньше 0.
В очереди нет сообщения необходимого типа, а в параметре msgflg установлен флаг IPC_NOWAIT.

СООТВЕТСТВИЕ СТАНДАРТАМ

SVr4, POSIX.1-2001.

ЗАМЕЧАНИЯ

Включение файлов <sys/types.h> и <sys/ipc.h> не требуется в Linux или любых версий POSIX. Однако, некоторые старые реализации требуют включения данных заголовочных файлов, и это также требуется по SVID. В приложениях, которые нужно перенести на такие старые системы, может потребоваться включить данных заголовочные файлы.

Аргумент msgp в libc4, libc5, glibc 2.0, glibc 2.1 объявлен как struct msgbuf *. В glibc 2.2, в соответствии с SUSv2 и SUSv3, он объявлен как void *.

На работу системного вызова msgsnd() влияют следующие системные ограничения на ресурсы очереди сообщений:

Максимальный размер текста сообщения: по умолчанию он равен 8192 байтам (в Linux это ограничение можно прочитать и изменить через /proc/sys/kernel/msgmax).
Максимальный размер по умолчанию очереди сообщений: 16384 байта (в Linux это ограничение можно прочитать и изменить через /proc/sys/kernel/msgmnb). Суперпользователь может устанавливать больший размер очереди сообщений, чем MSGMNB при помощи системного вызова msgctl(2).

Реализация не накладывает существенных ограничений на максимальное количество заголовков сообщений (MSGTQL) и на максимальный размер в байтах пула сообщений (MSGPOOL).

СМОТРИТЕ ТАКЖЕ

msgctl(2), msgget(2), capabilities(7), mq_overview(7), svipc(7)

2012-05-31 Linux