您的位置:首页 > 其它

IPC通信:Posix消息队列读,写

2012-04-16 09:24 399 查看
创建消息队列的程序:

#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>

#define MQ_NAME ("/tmp")
#define MQ_FLAG (O_RDWR | O_CREAT | O_EXCL) // 创建MQ的flag
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) // 设定创建MQ的权限

int main()

{
mqd_t posixmq;
int rc = 0;

/*
函数说明:函数创建或打开一个消息队列
返回值:成功返回消息队列描述符,失败返回-1,错误原因存于errno中
*/
posixmq = mq_open(MQ_NAME, MQ_FLAG, FILE_MODE, NULL);

if(-1 == posixmq)
{
perror("创建MQ失败");
exit(1);
}

/*
函数说明:关闭一个打开的消息队列,表示本进程不再对该消息队列读写
返回值:成功返回0,失败返回-1,错误原因存于errno中
*/
rc = mq_close(posixmq);
if(0 != rc)
{
perror("关闭失败");
exit(1);
}

#if 0
/*
函数说明:删除一个消息队列,好比删除一个文件,其他进程再也无法访问
返回值:成功返回0,失败返回-1,错误原因存于errno中
*/
rc = mq_unlink(MQ_NAME);
if(0 != rc)
{
perror("删除失败");
exit(1);
}

return 0;
#endif
}


编译并执行:

root@linux:/mnt/hgfs/C_libary# gcc -o crtmq crtmq.c -lrt
root@linux:/mnt/hgfs/C_libary# ./crtmq
程序并没有删除消息队列(消息队列有随内核持续性),如再次执行该程序则会给出错误信息:
root@linux:/mnt/hgfs/C_libary# ./crtmq
创建MQ失败: File  exit(0)


向消息队列写消息的程序:

消息队列的读写主要使用下面两个函数:
/*头文件*/
#include <mqueue.h>

/*返回:若成功则为消息中字节数,若出错则为-1 */
int mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned msg_prio);

/*返回:若成功则为0, 若出错则为-1*/
ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned *msg_prio);

/*消息队列属性结构体*/
struct mq_attr {
long mq_flags;       /* Flags: 0 or O_NONBLOCK */
long mq_maxmsg;      /* Max. # of messages on queue */
long mq_msgsize;     /* Max. message size (bytes) */
long mq_curmsgs;     /* # of messages currently in queue */
};


#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>

/*向消息队列发送消息,消息队列名及发送的信息通过参数传递*/
int main(int argc, char *argv[])
{
mqd_t mqd;
char *ptr;
size_t len;
unsigned int prio;
int rc;

if(argc != 4)
{
printf("Usage: sendmq <name> <bytes> <priority>\n");
exit(1);
}

len = atoi(argv[2]);
prio = atoi(argv[3]);

//只写模式找开消息队列
mqd = mq_open(argv[1], O_WRONLY);
if(-1 == mqd)
{
perror("打开消息队列失败");
exit(1);
}

// 动态申请一块内存
ptr = (char *) calloc(len, sizeof(char));
if(NULL == ptr)
{
perror("申请内存失败");
mq_close(mqd);
exit(1);
}

/*向消息队列写入消息,如消息队列满则阻塞,直到消息队列有空闲时再写入*/
rc = mq_send(mqd, ptr, len, prio);
if(rc < 0)
{
perror("写入消息队列失败");
mq_close(mqd);
exit(1);
}

// 释放内存
free(ptr);
return 0;
}


编译并执行:

root@linux:/mnt/hgfs/C_libary# gcc -o sendmq sendmq.c -lrt
root@linux:/mnt/hgfs/C_libary# ./sendmq /tmp 30 15
root@linux:/mnt/hgfs/C_libary# ./sendmq /tmp 30 16
root@linux:/mnt/hgfs/C_libary# ./sendmq /tmp 30 17
root@linux:/mnt/hgfs/C_libary# ./sendmq /tmp 30 18


  上面先后向消息队列“/tmp”写入了四条消息,因为先前创建的消息队列只允许存放3条消息,本次第四次写入时程序会阻塞。直到有另外进程从消息队列取走消息后本次写入才成功返回。

读消息队列:

#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>

/*读取某消息队列,消息队列名通过参数传递*/
int main(int argc, char *argv[])
{
mqd_t mqd;
struct mq_attr attr;
char *ptr;
unsigned int prio;
size_t n;
int rc;

if(argc != 2)
{
printf("Usage: readmq <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);
}

/*接收一条消息*/
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);
return 0;
}


编译并执行:

root@linux:/mnt/hgfs/C_libary# vi readmq.c
root@linux:/mnt/hgfs/C_libary# vi readmq.c
root@linux:/mnt/hgfs/C_libary# gcc -o readmq readmq.c -lrt
root@linux:/mnt/hgfs/C_libary# ./readmq /tmp
读取 30 字节
优先级为 18
root@linux:/mnt/hgfs/C_libary# ./readmq /tmp
读取 30 字节
优先级为 17
root@linux:/mnt/hgfs/C_libary# ./readmq /tmp
读取 30 字节
优先级为 16
root@linux:/mnt/hgfs/C_libary# ./readmq /tmp
读取 30 字节
优先级为 15
root@linux:/mnt/hgfs/C_libary# ./readmq /tmp


  程序执行五次,第一次执行完,先前阻塞在写处的程序成功返回。第五次执行,因为消息队列已经为空,程序阻塞。直到另外的进程向消息队列写入一条消息。另外,还可以看出Posix消息队列每次读出的都是消息队列中优先级最高的消息。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: