Posix消息队列使用非阻塞mq_receive的信号通知

<span style="font-family:Comic Sans MS;font-size:14px;">//msgcreate.c:
#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>

#define FILE_MODE S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH

struct mq_attr	attr;	/* mq_maxmsg and mq_msgsize both init to 0 */

int main(int argc, char **argv)
{
	int		c, flags;
	mqd_t	mqd;

	flags = O_RDWR | O_CREAT;
	while ( (c = getopt(argc, argv, "em:z:")) != -1) {
		switch (c) {
		case 'e':
			flags |= O_EXCL;
			break;

		case 'm':
			attr.mq_maxmsg = atol(optarg);
			break;

		case 'z':
			attr.mq_msgsize = atol(optarg);
			break;
		}
	}
	if (optind != argc - 1)
		perror("usage: mqcreate [ -e ] [ -m maxmsg -z msgsize ] <name>");

	if ((attr.mq_maxmsg != 0 && attr.mq_msgsize == 0) ||
		(attr.mq_maxmsg == 0 && attr.mq_msgsize != 0))
		perror("must specify both -m maxmsg and -z msgsize");

	mqd = mq_open(argv[optind], flags, FILE_MODE,
				  (attr.mq_maxmsg != 0) ? &attr : NULL);

	mq_close(mqd);
	exit(0);
}

//msgsend.c:
#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>
 
int main(int argc, char **argv)
{
	mqd_t	mqd;
	void	*ptr;
	size_t	len;
	size_t	prio;

	if (argc != 4)
		perror("usage: mqsend <name> <#bytes> <priority>");
	len = atoi(argv[2]);
	prio = atoi(argv[3]);

	mqd = mq_open(argv[1], O_WRONLY);

	ptr = calloc(len, sizeof(char));
	mq_send(mqd, ptr, len, prio);

	exit(0);
}



//mqnotifysig3.c:

#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>
 
volatile sig_atomic_t mqflag; // 被信息处理函数设置为非0值
void sig_usr1(int);
 
int main(int argc, char *argv[])
{
    mqd_t mqd;
    char *ptr;
    struct mq_attr attr;
    struct sigevent sigev;
    sigset_t zeromask, newmask, oldmask; // 信号集
    unsigned int prio;
    size_t n;
    int rc;
 
    if(argc != 2)
    {
        printf("Usage: mqnotifysig3 <name>\n");
        exit(1);
    }
 
    /*只读模式打开消息队列,同时指定非阻塞标志*/
    mqd = mq_open(argv[1], O_RDONLY);
    if(mqd < 0)
    {
        perror("打开消息队列失败");
        exit(1);
    }
 
     
    /*取得消息队列属性*/
    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);
    }
 
    /*初始化信号集*/
    if(sigemptyset(&zeromask) < 0) {perror("初始化信号集失败");}
    if(sigemptyset(&newmask) < 0) {perror("初始化信号集失败");}
    if(sigemptyset(&oldmask) < 0) {perror("初始化信号集失败");}
    if(sigaddset(&newmask, SIGUSR1) < 0) {perror("添加SIGUSR1信号失败");}
 
    //注册信号函数
    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(;;)
    {
        if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0 ) {perror("阻塞信号失败");}
        while(0 == mqflag)
        {
            sigsuspend(&zeromask); /*等待信号到来*/
        }
        mqflag = 0;
         
        rc = mq_notify(mqd, &sigev); // 读取前需要再次注册
        if(rc < 0)
        {
            perror("通知注册失败");
            mq_close(mqd);
            free(ptr);
            exit(1);
        }
 
        while((n = mq_receive(mqd, ptr, attr.mq_msgsize, &prio)) >= 0)
        {
            printf("Read %ld bytes\nPrio: %d\n", n, prio);
        }
        if(EAGAIN != errno)
        {
            perror("读取失败");
        }
 
        sigprocmask(SIG_UNBLOCK, &newmask, NULL);
    }
    exit(0);
}
 
void sig_usr1(int signo)
{
    mqflag = 1;
    return;
}</span>


gcc -o mqnotifysig3 mqnotifysig3.c -lrt
gcc -o msgsend msgsend.c -lrt
gcc -o msgcreate msgcreate.c -lrt


验证:
1. 创建消息队列: ./msgcreate /mqfile
2. 执行主程序: ./mqnotifysig3 /mqfile
3. 再开一个窗口执行发送消息: 
./msgsend /mqfile 193 33
输出如下:
Read 193 bytes
Prio: 33


./msgsend /mqfile 22 33
输出如下:
Read 22 bytes
Prio: 33


ref: 

unpipc v2 P73

http://my.oschina.net/renhc/blog/35710


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值