Provided by: manpages-ru-dev_4.21.0-2_all bug

ИМЯ

       mq_notify - включает уведомление при поступлении сообщения

LIBRARY

       Real-time library (librt, -lrt)

СИНТАКСИС

       #include <mqueue.h>
       #include <signal.h>           /* Definition of SIGEV_* constants */

       int mq_notify(mqd_t mqdes, const struct sigevent *sevp);

ОПИСАНИЕ

       Функция  mq_notify()  позволяет  вызывающему  процессу регистрироваться или отменять регистрацию доставки
       анонимных уведомлений при появлении нового сообщения в пустой очереди  сообщений,  на  которую  ссылается
       дескриптор очереди сообщений mqdes.

       Аргумент  sevp  является  указателем  на  структуру sigevent. Определение и описание структуры смотрите в
       sigevent(7).

       Если sevp не равен null, то mq_notify() регистрирует  вызывающий  процесс  для  получения  уведомлений  о
       сообщениях. В поле sigev_notify структуры sigevent, на которую указывает sevp, задаётся способ выполнения
       уведомления. Это поле может содержать одно из следующих значений:

       SIGEV_NONE
              «Нулевое»  уведомление:  хотя  вызывающий процесс и регистрируется как уведомляемый, при появлении
              сообщения уведомление не будет отправлено.

       SIGEV_SIGNAL
              Уведомлять процесс посредством отправки сигнала, указанного в sigev_signo. Подробности смотрите  в
              sigevent(7).  Поле  si_code структуры siginfo_t будет изменено на SI_MESGQ. Также, значение si_pid
              будет изменено на PID процесса, который посылается сообщение, а значение  si_uid будет изменено на
              реальный пользовательский ID посылающего процесса.

       SIGEV_THREAD
              При доставке сообщения вызвать sigev_notify_function, как если бы это была начальная функция новой
              нити. Подробности смотрите в sigevent(7).

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

       Если sevp равно NULL и вызывающий процесс  уже  зарегистрирован  принимать  сообщения  для  этой  очереди
       сообщений,  то  регистрация  удаляется; после этого другой процесс может зарегистрироваться для получения
       уведомлений о сообщениях в этой очереди.

       Уведомление о сообщение возникает только при поступлении нового сообщения и если очередь  до  этого  была
       пуста.  Если очередь не пуста на момент вызова mq_notify(), то уведомление будет происходить только после
       опустошения очереди и поступлении нового сообщения.

       Если другой процесс или нить ожидают чтения сообщения из пустой очереди с помощью mq_receive(3),  то  все
       регистрации по уведомлению игнорируются; сообщение доставляется процесс или нити вызвавшей mq_receive(3),
       и регистрация уведомления о сообщении остаётся как была.

       Уведомление выполняется один раз: после доставки уведомления регистрация удаляется и другой процесс может
       зарегистрироваться для уведомления. Если уведомлённый процесс хочет получить следующее уведомление, то он
       может  использовать  mq_notify()  для  запроса  уведомления  в  дальнейшем.  Это  должно  быть сделано до
       исчезновения всех непрочитанных сообщений из очереди (переключение очереди в неблокирующий режим  полезно
       для опустошения очереди сообщений без блокировки, если очередь пуста).

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

       При  успешном  выполнении  mq_notify()  возвращает  0; при ошибке возвращает -1, а в errno помещается код
       ошибки.

ОШИБКИ

       EBADF  В mqdes размещён некорректный дескриптор очереди сообщений.

       EBUSY  Другой процесс уже зарегистрировался, чтобы получать уведомление из этой очереди сообщений.

       EINVAL Значение  sevp->sigev_notify  содержит  недопустимое  значение;   или   sevp->sigev_notify   равно
              SIGEV_SIGNAL и sevp->sigev_signo не содержит корректного номера сигнала.

       ENOMEM Недостаточно памяти.

       В  POSIX.1-2008  сказано,  что  реализация  может  генерировать  ошибку  EINVAL,  если sevp равно NULL, и
       вызывающий ещё не зарегистрирован для получения уведомлений из очереди mqdes.

АТРИБУТЫ

       Описание терминов данного раздела смотрите в attributes(7).
       ┌─────────────────────────────────────────────────────────────────────┬──────────────────────┬──────────┐
       │ ИнтерфейсАтрибутЗначение │
       ├─────────────────────────────────────────────────────────────────────┼──────────────────────┼──────────┤
       │ mq_notify()                                                         │ Безвредность в нитях │ MT-Safe  │
       └─────────────────────────────────────────────────────────────────────┴──────────────────────┴──────────┘

СТАНДАРТЫ

       POSIX.1-2001.

ЗАМЕЧАНИЯ

   Отличия между библиотекой C и ядром
       В glibc библиотечная функция mq_notify() реализована на основе системного вызова с тем  же  именем.  Если
       sevp  равно  NULL  или  задаёт  механизм  уведомления  не  SIGEV_THREAD, то библиотечная функция напрямую
       вызывает системный вызов. Большая часть реализации SIGEV_THREAD располагается внутри библиотеки, а  не  в
       ядре  (эта  необходимость  возникает  из-за  того,  что нить, вовлечённая в обработку уведомления, должна
       управляться в библиотечной реализации C нитей  POSIX).  В  реализации  задействуется  неструктурированный
       сокет netlink(7) и создаётся новая нить для каждого уведомления, доставляемого процессу.

ПРИМЕРЫ

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

   Исходный код программы
       #include <mqueue.h>
       #include <pthread.h>
       #include <signal.h>
       #include <stdio.h>
       #include <stdlib.h>
       #include <unistd.h>

       #define handle_error(msg) \
           do { perror(msg); exit(EXIT_FAILURE); } while (0)

       static void                     /* начальная функция нити */
       tfunc(union sigval sv)
       {
           struct mq_attr attr;
           ssize_t nr;
           void *buf;
           mqd_t mqdes = *((mqd_t *) sv.sival_ptr);

       /* Определяем максимальный размер сообщения; выделяем буфер для принимаемого сообщения */

           if (mq_getattr(mqdes, &attr) == -1)
               handle_error("mq_getattr");
           buf = malloc(attr.mq_msgsize);
           if (buf == NULL)
               handle_error("malloc");

           nr = mq_receive(mqdes, buf, attr.mq_msgsize, NULL);
           if (nr == -1)
               handle_error("mq_receive");

           printf("Read %zd bytes from MQ\n", nr);
           free(buf);
           exit(EXIT_SUCCESS);         /* Завершение процесса */
       }

       int
       main(int argc, char *argv[])
       {
           mqd_t mqdes;
           struct sigevent sev;

           if (argc != 2) {
               fprintf(stderr, "Использование: %s <mq-name>\n", argv[0]);
               exit(EXIT_FAILURE);
           }

           mqdes = mq_open(argv[1], O_RDONLY);
           if (mqdes == (mqd_t) -1)
               handle_error("mq_open");

           sev.sigev_notify = SIGEV_THREAD;
           sev.sigev_notify_function = tfunc;
           sev.sigev_notify_attributes = NULL;
           sev.sigev_value.sival_ptr = &mqdes;   /* аргументы функции нити */
           if (mq_notify(mqdes, &sev) == -1)
               handle_error("mq_notify");

           pause();    /* процесс будет завершён из функции нити */
       }

СМ. ТАКЖЕ

       mq_close(3),   mq_getattr(3),   mq_open(3),   mq_receive(3),  mq_send(3),  mq_unlink(3),  mq_overview(7),
       sigevent(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>

       Этот перевод является бесплатной документацией; прочитайте Стандартную общественную лицензию GNU версии 3
       или более позднюю, чтобы узнать об условиях авторского права. Мы не несем НИКАКОЙ ОТВЕТСТВЕННОСТИ.

       Если  вы обнаружите ошибки в переводе этой страницы руководства, пожалуйста, отправьте электронное письмо
       на man-pages-ru-talks@lists.sourceforge.net.

Linux man-pages 6.03                           15 декабря 2022 г.                                   mq_notify(3)