MQ_NOTIFY - Linux手册页
Linux程序员手册 第3部分
更新日期: 2020-06-09
名称
mq_notify-注册消息可用时的通知
语法
#include <mqueue.h> int mq_notify(mqd_t mqdes, const struct sigevent *sevp);
与-lrt链接。
说明
当新消息到达消息队列描述符mqdes所引用的空消息队列时,mq_notify()允许调用进程注册或注销以传递异步通知。
sevp参数是sigevent结构的指针。有关此结构的定义和一般详细信息,请参见sigevent(7)。
如果sevp是非空指针,则mq_notify()注册调用过程以接收消息通知。 sevp指向的sigevent结构的sigev_notify字段指定如何执行通知。该字段具有以下值之一:
- SIGEV_NONE
- "空"通知:呼叫过程已注册为通知目标,但是当消息到达时,不会发送任何通知。
- SIGEV_SIGNAL
- 通过发送sigev_signo中指定的信号来通知该过程。有关常规详细信息,请参见sigevent(7)。 siginfo_t结构的si_code字段将设置为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;否则,返回0。如果出错,则返回-1,并设置errno表示错误。
错误说明
- EBADF
- 在mqdes中指定的消息队列描述符无效。
- EBUSY
- 已经注册了另一个进程来接收此消息队列的通知。
- EINVAL
- sevp->sigev_notify不是允许的值之一;或sevp->sigev_notify是SIGEV_SIGNAL,而sevp->sigev_signo不是有效的信号编号。
- ENOMEM
- 内存不足。
POSIX.1-2008说,如果sevp为NULL,并且调用方当前未注册为接收队列mqdes的通知,则实现可能会生成EINVAL错误。
属性
有关本节中使用的术语的说明,请参见attribute(7)。
Interface | Attribute | Value |
mq_notify() | Thread safety | MT-Safe |
遵循规范
POSIX.1-2001。
备注
C library/kernel differences
在glibc实现中,mq_notify()库函数是在同名的系统调用之上实现的。当sevp为NULL或指定除SIGEV_THREAD以外的通知机制时,库函数将直接调用系统调用。对于SIGEV_THREAD,大部分实现都驻留在库中,而不是内核中。 (这一定是必须的,因为处理通知的线程是必须由C库POSIX线程实现管理的线程。)该实现涉及使用原始netlink(7)套接字并为每个通知创建一个新线程。交付给流程。
示例
以下程序为在其命令行参数中命名的消息队列注册一个通知请求。通过创建线程来执行通知。该线程执行一个函数,该函数从队列中读取一条消息,然后终止该进程。
Program source
#include <pthread.h> #include <mqueue.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #define handle_error(msg) \ do { perror(msg); exit(EXIT_FAILURE); } while (0) static void /* Thread start function */ tfunc(union sigval sv) { struct mq_attr attr; ssize_t nr; void *buf; mqd_t mqdes = *((mqd_t *) sv.sival_ptr); /* Determine max. msg size; allocate buffer to receive msg */ 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); /* Terminate the process */ } int main(int argc, char *argv[]) { mqd_t mqdes; struct sigevent sev; if (argc != 2) { fprintf(stderr, "Usage: %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; /* Arg. to thread func. */ if (mq_notify(mqdes, &sev) == -1) handle_error("mq_notify"); pause(); /* Process will be terminated by thread function */ }
另外参见
mq_close(3),mq_getattr(3),mq_open(3),mq_receive(3),mq_send(3),mq_unlink(3),mq_overview(7),sigevent(7)
出版信息
这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/。