mq_notify()函数为指定队列建立或删除异步事件通知,建立通知即某空消息队列中如有新的消息,会发送一个信号或创建一个线程来执行指定的函数。
#include <mqueue.h>
int mq_notify(mqd_t mqdes, const struct sigevent *notification);
成功返回0,出错则为-1
给出struct sigevent定义:
union signal
{
int sival_int; /*整数值*/
void *sival_ptr; /*指针值*/
};
struct sigevent
{
int sigev_notify; /*通知类型:SIGEV_NONE、SIGEV_SIGNAL、SIGEV_THREAD*/
int sigev_signo; /*信号值*/
union sigval sigev_value; /*传递给信号处理函数或线程的信号值*/
void (*sigev_notify_function)(union sigval); /*线程处理函数*/
pthread_attr_t *sigev_notify_attributes; /*线程属性*/
};
下面给出示例代码:
#include <stdio.h>
#include <stdlib.h>
#include <mqueue.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
mqd_t mqd;
struct mq_attr attr;
struct sigevent sigev;
char *ptr;
unsigned int prio;
size_t n;
int rc;
void sig_usr1(int signo);
/*读取某消息队列,消息队列名通过参数传递*/
/*当有消息放置到某个空的队列中时产生SIGUSR1信号*/
int main(int argc, char *argv[])
{
if(argc != 2)
{
printf("Usage: mqnotifysig1 <name>\n");
exit(1);
}
/*只读模式打开消息队列*/
mqd = mq_open(argv[1], O_RDONLY);
if(mqd < 0)
{
perror("打开消息队列失败");
exit(1);
}
// 取得消息队列属性,根据mq_msgsize动态申请内存
rc = mq_getattr(mqd, &attr);
if(rc < 0)
{
perror("取得消息队列属性失败");
exit(1);
}
/*动态申请保证能存放单条消息的内存*/
ptr = calloc(attr.mq_msgsize, sizeof(char));
if(NULL == ptr)
{
printf("动态申请内存失败\n");
mq_close(mqd);
exit(1);
}
//注册信号函数
signal(SIGUSR1, sig_usr1);
sigev.sigev_notify = SIGEV_SIGNAL;
sigev.sigev_signo = SIGUSR1;
//注册通知
rc = mq_notify(mqd, &sigev); // 读取前需要再次注册
if(rc < 0)
{
perror("通知注册失败");
mq_close(mqd);
free(ptr);
exit(1);
}
for(;;)
{
pause();
}
return 0;
}
void sig_usr1(int signo)
{
rc = mq_notify(mqd, &sigev); // 读取前需要再次注册
if(rc < 0)
{
perror("通知注册失败");
mq_close(mqd);
free(ptr);
exit(1);
}
/*接收一条消息*/
n = mq_receive(mqd, ptr, attr.mq_msgsize, &prio);
if(n < 0)
{
perror("读取失败");
mq_close(mqd);
free(ptr);
exit(1);
}
printf("读取 %ld 字节\n优先级为 %u\n", (long)n, prio);
}
编译并执行:
[infor@s123 PosixMq]$ gcc -o mqnotifysig1 mqnotifysig1.c -lrt
[infor@s123 PosixMq]$ ./mqnotifysig1 /tmp
此时消息队列内没有消息,程序进入睡眠,等待信号到来。再开启一个终端,通过另外的程序往消息队列写消息:
[infor@s123 PosixMq]$ ./sendmq /tmp 200 16
[infor@s123 PosixMq]$ ./sendmq /tmp 100 17
[infor@s123 PosixMq]$ ./sendmq /tmp 50 18
可以看到先前的程序:
[infor@s123 PosixMq]$ gcc -o mqnotifysig1 mqnotifysig1.c -lrt
[infor@s123 PosixMq]$ ./mqnotifysig1 /tmp
读取 200 字节
优先级为 16
读取 100 字节
优先级为 17
读取 50 字节
优先级为 18
mq_notify函数使用规则:
1、如果mq_notify()的notification参数非空,则表明将当前进程注册为接收某队列的通知;
2、如果mq_notify()的notification参数为空,则表明之前已存在的注册将被撤消;
3、一个消息队列任意时刻只能由一个进程注册;
4、如有其他进程mq_receive阻塞在该消息队列时,信号不会发出,即mq_receive调用优先级更高;
5、通知被发送给注册进程时,注册即被撤消,须重新注册。
注:上面程序其实是有问题,本处只做mq_notify函数的使用示例。
2011-11-18 任洪彩 qdurenhongcai@163.com
转载请注明出处。
来源:oschina
链接:https://my.oschina.net/u/101347/blog/35539