Posix 消息队列 实例分析

一、概述

在linux应用开发中,消息队列的应用场景很普遍,比如最常见得 生产 -- 消费模型,一方产生数据,并把数据放入队列中,而另一方从队列中取数据。linux中的消息队列的主要用途为进程间通信,当然,也可以进行 “线程间通信”。

    我们可以简单的理解为:

    (1)创建了一个消息队列,相当于在内核层面,创建了一个链表,这也就意味着这个消息队列,在不主动删除的情况下,会一直存在,即便是创建它的进程退出后,该消息队列仍然存在。消息队列在内存中可能的布局如下:

    (2)消息队列 相当于是“全局”的,我们知道要知道消息队列的名字 或者 id,那么任何进程或线程都是可以访问该消息队列的,这也是为什么可以通过消息队列实现IPC。

    在linux中,消息队列有两种,分别为Posix消息队列 和 System V,这里不详述这两者的区别,只简单的提一下,System V是内核级别的 老版本 消息队列,而Posix是标准接口的消息队列,Posix 消息队列应该也是基于System V 实现的,所以这里重点说 Posix消息队列。

二、Posix消息队列 API

#include <mqueue.h>

// 打开或创建一个消息队列, name 必须是 "/" 开头,而且只能有一个 /
mqd_t mq_open(const char *name, int oflag);

mqd_t mq_open(const char *name, int oflag, mode_t mode,
                     struct mq_attr *attr);


// 向消息队列 mqdes中发送消息
int mq_send(mqd_t mqdes, const char *msg_ptr,
                     size_t msg_len, unsigned int msg_prio);


// 删除 消息队列
int mq_unlink(const char *name);

// 从消息队列中接收消息
ssize_t mq_receive(mqd_t mqdes, char *msg_ptr,
                          size_t msg_len, unsigned int *msg_prio);

// 关闭消息队列, 注意:关闭消息队列,并不会删除该消息队列
int mq_close(mqd_t mqdes);

// 每个消息队列有4个属性, 消息状态标志(阻塞...)|消息最多条数|每条消息的最大长度|当前消息cur

// 获取消息队列属性
int mq_getattr(mqd_t mqdes, struct mq_attr *attr);
// 设置消息队列属性
int mq_setattr(mqd_t mqdes, const struct mq_attr *attr, struct mq_attr *oattr);

三、代码示例

1、创建 Posix消息队列

#include <mqueue.h>

 static mqd_t mqd;

int create_mqueue(void)
{
	struct mq_attr attr;
	
	attr.mq_flags = 0;
	attr.mq_maxmsg = 10;        // 最多10条消息
	attr.mq_msgsize = 100;      // 每条消息长度最大 100byte
	attr.mq_curmsgs = 0;
    
    // 读写|创建 消息队列,名字为 "/my_queue", name 必须是 "/" 开头,而且只能有一个'/', 规定
	mqd = mq_open("/my_queue", O_RDWR|O_CREAT, 0666, &attr);
	if(mqd < 0){
		printf("mq_open error:%d\n", mqd);
		return -1;
	}
	return 0;
}

2、发送消息

int mqueue_send(char *msg, int len)
{
	int rc;
	mqd_t mq_cmd;
	struct mq_attr attr;
	attr.mq_flags = 0;
	attr.mq_maxmsg = OTA_MQUEUE_MSG_MAX;
	attr.mq_msgsize = OTA_MQUEUE_MSG_SIZE;
	attr.mq_curmsgs = 0;
    
    // 只写 的方式 打开或创建 消息队列
	mq_cmd = mq_open("/my_queue", O_WRONLY|O_CREAT, 0666, &attr);
	if(mq_cmd < 0){
		printf("mq open error:%d\n", mq_cmd);
		return -1;
	}

	rc = mq_send(mq_cmd, msg, len, 0);
	if(rc < 0){
		printf("mq send error:%d\n", rc);
		return -1;
	}

	if(mq_close(mq_cmd) < 0){
		printf("mq close error.\n");
		return -1;
	}

	return 0;
}

3、接收消息

    Posix 默认为 阻塞的,所以我们可以在一个线程中阻塞接收 消息,这样实时性更好一些:

int mqueue_receive(char *msg)
{
	int rc;
	if(mqd < 0){
		printf("mqueue has no open.\n");
		return -1;
	}

	rc = mq_receive(mqd, msg, 100, NULL);
	if(rc < 0){
		printf("mq_receive error: %d \n", rc);
	}

	return rc;
}

    注意:我们在 使用 mq_receive时,参数 “消息长度”,可以设置成该消息队列属性的 “消息最大长度”,这样就能实现在未知消息多长的情况下,接收消息的所有内容,返回的就是 接收的消息 长度。

小结

    1、Posix 消息队列使用起来还是比较方便的。

   2、一个进程终止时,它所打开着的消息队列都会关闭,就像调用了mq_close一样,不过此时的时候,可能是自己的愿意,发下如果没有close,再次打开可能会异常,所以进行保持好习惯,随用随open,然后close

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值