Provided by: manpages-ru-dev_4.27.0-1_all bug

НАИМЕНОВАНИЕ

       msgrcv, msgsnd - операции с очередью сообщений System V

БИБЛИОТЕКА

       Стандартная библиотека языка C (libc, -lc)

ОБЗОР

       #include <sys/msg.h>

       int msgsnd(int msqid, const void msgp[.msgsz], size_t msgsz,
                      int msgflg);

       ssize_t msgrcv(int msqid, void msgp[.msgsz], size_t msgsz, long msgtyp,
                      int msgflg);

ОПИСАНИЕ

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

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

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

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

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

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

       •  Добавление  нового  сообщения  привело бы к превышению общего количества байт очереди над максимальным
          количеством размером очереди (поле msg_qbytes).

       •  Добавление другого  сообщения  привело  бы  к  превышению  общего  количества  сообщений  очереди  над
          максимальным   количеством   размером   очереди   (поле   msg_qbytes).  Эта  проверка  необходима  для
          предотвращения помещения в  очередь  бесконечного  количества  сообщений  нулевой  длины.  Хотя  такие
          сообщения не содержат данных, тем не менее, они потребляют (блокируют) память ядра.

       Если  в очереди недостаточно места, то по умолчанию 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.

       Если  в  msgflg (смотрите ниже ) не указан MSG_COPY, то в аргументе msgtyp указывается тип запрашиваемого
       сообщения:

       •  Если msgtyp равно нулю, то читается первое сообщение в очереди.

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

       •  Если msgtyp меньше нуля, то из очереди читается первое сообщение  со  значением,  меньшим  или  равным
          абсолютному значению msgtyp.

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

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

       MSG_COPY (начиная с Linux 3.8)
              Забирает копию сообщения без удаления из начальной позиции в очереди, заданной в msgtyp (сообщения
              нумеруются начиная с 0).

              Этот флаг должен указываться вместе с IPC_NOWAIT; в этом случае, если в заданной позиции сообщение
              отсутствует, то вызов завершается с ошибкой ENOMSG немедленно.  Флаги  MSG_COPY  и  MSG_EXCEPT  не
              могут указываться вместе в msgflg, так как кардинально изменяют смысл msgtyp.

              Флаг  MSG_COPY был добавлен для реализации способности ядра для контрольных точек/восстановления и
              доступен только, если ядро собрано с параметром CONFIG_CHECKPOINT_RESTORE.

       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 становится равным текущему времени.

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

       On success, msgsnd()  returns 0 and msgrcv()  returns the number of bytes actually copied into the  mtext
       array.  On failure, both functions return -1, and set errno to indicate the error.

ОШИБКИ

       msgsnd()  can fail with the following errors:

       EACCES Вызывающий  процесс  не  имеет  прав записи в очередь сообщений и не имеет мандата CAP_IPC_OWNER в
              пользовательском пространстве имён, которое управляет его пространством имён IPC.

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

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

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

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

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

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

       msgrcv()  can fail with the following errors:

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

       EACCES Вызывающий   процесс  не  имеет  прав  чтобы  прочитать  очереди  сообщений  и  не  имеет  мандата
              CAP_IPC_OWNER в пространстве имён пользователя, который управляет его пространством имён IPC.

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

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

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

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

       EINVAL (начиная с Linux 3.14)
              В msgflg указан флаг MSG_COPY, но нет IPC_NOWAIT.

       EINVAL (начиная с Linux 3.14)
              В msgflg указаны MSG_COPY и MSG_EXCEPT.

       ENOMSG В очереди нет сообщения необходимого типа, а в параметре msgflg установлен флаг IPC_NOWAIT.

       ENOMSG Флаги IPC_NOWAIT и MSG_COPY указаны в msgflg, но в очереди содержится меньше msgtyp сообщений.

       ENOSYS (начиная с Linux 3.8)
              Both MSG_COPY and IPC_NOWAIT were specified in msgflg, and  this  kernel  was  configured  without
              CONFIG_CHECKPOINT_RESTORE.

СТАНДАРТЫ

       POSIX.1-2008.

       Флаги MSG_EXCEPT и MSG_COPY есть только в Linux; их определения можно получить указав макрос тестирования
       свойств _GNU_SOURCE.

ИСТОРИЯ

       POSIX.1-2001, SVr4.

       Аргумент msgp в glibc 2.0 и 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.
              Привилегированный процесс (Linux: процесс с мандатом CAP_SYS_RESOURCE) может устанавливать  размер
              очереди сообщений больше чем MSGMNB при помощи вызова msgctl() с операцией IPC_SET.

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

ОШИБКИ

       В Linux 3.13 и старее, если msgrcv() был вызван с флагом MSG_COPY flag,  но  без  IPC_NOWAIT,  и  очередь
       сообщений  содержала  менее  msgtyp  сообщений, то вызов блокировал выполнения до тех пор, пока следующее
       сообщение не записывалось в очередь. written to the queue. В этот момент вызов возвращал копию сообщения,
       независимо от того, что сообщение было в начальной позиции msgtyp. Этот  дефект  был  исправлен  в  Linux
       3.14.

       Указание  обоих  флагов  MSG_COPY  и  MSC_EXCEPT в msgflg является логической ошибкой (так как для флагов
       по-разному интерпретируется msgtyp). В Linux 3.13 и старее эта  ошибка  не  определялась  msgrcv().  Этот
       дефект был исправлен в Linux 3.14.

ПРИМЕРЫ

       Представленная ниже программа показывает использование msgsnd() и msgrcv().

       В  первый  раз программа запускается с параметром -s для отправки сообщения, а в второй — с параметром -r
       для получения сообщения.

       Пример сеанса работы с программой:

           $ ./a.out -s
           отправка: дата сообщения Wed Mar  4 16:25:45 2015

       $ ./a.out -r
       приём: дата сообщения Wed Mar  4 16:25:45 2015

   Исходный код программы

       #include <errno.h>
       #include <stdio.h>
       #include <stdlib.h>
       #include <sys/ipc.h>
       #include <sys/msg.h>
       #include <time.h>
       #include <unistd.h>

       struct msgbuf {
           long mtype;
           char mtext[80];
       };

       static void
       usage(char *prog_name, char *msg)
       {
           if (msg != NULL)
               fputs(msg, stderr);

           fprintf(stderr, "Usage: %s [options]\n", prog_name);
           fprintf(stderr, "Options are:\n");
           fprintf(stderr, "-s        send message using msgsnd()\n");
           fprintf(stderr, "-r        read message using msgrcv()\n");
           fprintf(stderr, "-t        message type (default is 1)\n");
           fprintf(stderr, "-k        message queue key (default is 1234)\n");
           exit(EXIT_FAILURE);
       }

       static void
       send_msg(int qid, int msgtype)
       {
           time_t         t;
           struct msgbuf  msg;

           msg.mtype = msgtype;

           time(&t);
           snprintf(msg.mtext, sizeof(msg.mtext), "a message at %s",
                    ctime(&t));

           if (msgsnd(qid, &msg, sizeof(msg.mtext),
                      IPC_NOWAIT) == -1)
           {
               perror("msgsnd error");
               exit(EXIT_FAILURE);
           }
           printf("sent: %s\n", msg.mtext);
       }

       static void
       get_msg(int qid, int msgtype)
       {
           struct msgbuf msg;

           if (msgrcv(qid, &msg, sizeof(msg.mtext), msgtype,
                      MSG_NOERROR | IPC_NOWAIT) == -1) {
               if (errno != ENOMSG) {
                   perror("msgrcv");
                   exit(EXIT_FAILURE);
               }
               printf("No message available for msgrcv()\n");
           } else {
               printf("message received: %s\n", msg.mtext);
           }
       }

       int
       main(int argc, char *argv[])
       {
           int  qid, opt;
           int  mode = 0;               /* 1 = send, 2 = receive */
           int  msgtype = 1;
           int  msgkey = 1234;

           while ((opt = getopt(argc, argv, "srt:k:")) != -1) {
               switch (opt) {
               case 's':
                   mode = 1;
                   break;
               case 'r':
                   mode = 2;
                   break;
               case 't':
                   msgtype = atoi(optarg);
                   if (msgtype <= 0)
                       usage(argv[0], "-t option must be greater than 0\n");
                   break;
               case 'k':
                   msgkey = atoi(optarg);
                   break;
               default:
                   usage(argv[0], "Unrecognized option\n");
               }
           }

           if (mode == 0)
               usage(argv[0], "must use either -s or -r option\n");

           qid = msgget(msgkey, IPC_CREAT | 0666);

           if (qid == -1) {
               perror("msgget");
               exit(EXIT_FAILURE);
           }

           if (mode == 2)
               get_msg(qid, msgtype);
           else
               send_msg(qid, msgtype);

           exit(EXIT_SUCCESS);
       }

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

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

ПЕРЕВОД

       Русский  перевод  этой   страницы   руководства   разработал(и)   aereiae   <aereiae@gmail.com>,   Alexey
       <a.chepugov@gmail.com>, Azamat Hackimov <azamat.hackimov@gmail.com>, Dmitriy S. Seregin <dseregin@59.ru>,
       Dmitry  Bolkhovskikh  <d20052005@yandex.ru>,  ITriskTI <ITriskTI@gmail.com>, Max Is <ismax799@gmail.com>,
       Yuri  Kozlov  <yuray@komyakino.ru>,  Иван  Павлов   <pavia00@gmail.com>,   Малянов   Евгений   Викторович
       <maljanow@outlook.com> и Kirill Rekhov <krekhov.dev@gmail.com>

       Этот  перевод является свободной программной документацией; он распространяется на условиях общедоступной
       лицензии GNU (GNU General Public License - GPL, https://www.gnu.org/licenses/gpl-3.0.html  версии  3  или
       более поздней) в отношении авторского права, но БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ.

       Если  вы  обнаружите какие-либо ошибки в переводе этой страницы руководства, пожалуйста, сообщите об этом
       разработчику(ам)  по  его(их)  адресу(ам)  электронной  почты  или  по   адресу   списка рассылки русских
       переводчиков.

Справочные страницы Linux 6.9.1                  15 июня 2024 г.                                        MSGOP(2)