Provided by: manpages-ru-dev_4.19.0-7_all
ИМЯ
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⟩.