MQ_NOTIFY - Linux手册页

时间:2019-08-20 18:00:54  来源:igfitidea点击:

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)。

InterfaceAttributeValue
mq_notify()Thread safetyMT-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/