Provided by: manpages-ru-dev_4.19.0-7_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 ⟨https://www.gnu.org/licenses/gpl-3.0.html⟩ или более позднюю, чтобы
       узнать об условиях авторского права. Мы не несем НИКАКОЙ ОТВЕТСТВЕННОСТИ.

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