//msgcreate.c:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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 ] ");
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
#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc, char **argv)
{
mqd_t mqd;
void *ptr;
size_t len;
size_t prio;
if (argc != 4)
perror("usage: mqsend <#bytes> ");
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
#include
#include
#include
#include
#include
#include
#include
#include
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 \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;
}
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