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 представляет собой битовую маску из комбинации нуля или более следующих флагов:

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

MSG_EXCEPT
    Используется, если msgtyp больше 0, для чтения первого сообщения в очереди с типом, отличным от msgtyp.

MSG_NOERROR
    Используется для урезания текста сообщения, если его размер больше 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():

EACCES
    Вызывающий процесс не имеет прав записи в очередь сообщений и не имеет мандата CAP_IPC_OWNER.

EAGAIN
    Сообщение не может быть отправлено, так как размер очереди превысит лимит, равный msg_qbytes, а в параметре msgflg установлен флаг IPC_NOWAIT.

EFAULT
    Память с адресом, указанным msgp, недоступна.

EIDRM
    Очередь сообщений была удалена.

EINTR
    Процесс ждал свободного места в очереди и получил сигнал, который должен обработать.

EINVAL
    Задано неправильное значение msqid, не положительное значение mtype или неправильное значение msgsz (меньше 0, или больше системного лимита, заданного MSGMAX).

ENOMEM
    Недостаточно памяти в системе для копирования сообщения, указанного msgp.

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

E2BIG
    Длина текста получаемого сообщения больше, чем msgsz, а в поле msgflg не установлен флаг MSG_NOERROR.

EACCES
    Вызывающий процесс не имеет прав на чтение очереди сообщений и не имеет мандата CAP_IPC_OWNER.

EAGAIN
    Нет сообщения в очереди, а в msgflg указан флаг IPC_NOWAIT.

EFAULT
    Память с адресом, указанным msgp, недоступна.

EIDRM
    Процесс ждал приёма сообщения, и в это время очередь сообщений была удалена.

EINTR
    Во время ожидания приёма сообщения процесс получил сигнал; см. signal(7).

EINVAL
    Неверное значение msgqid или msgsz меньше 0.

ENOMSG
    В очереди нет сообщения необходимого типа, а в параметре 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() влияют следующие системные ограничения на ресурсы очереди сообщений:

MSGMAX
    Максимальный размер текста сообщения: по умолчанию он равен 8192 байтам (в Linux это ограничение можно прочитать и изменить через /proc/sys/kernel/msgmax).

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

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

СМОТРИТЕ ТАКЖЕ
msgctl(2), msgget(2), capabilities(7), mq_overview(7), svipc(7)