一、消息队列控制块:在include/rtdef.h中

#ifdef RT_USING_MESSAGEQUEUE
/**
* message queue structure
*/
struct rt_messagequeue
{
struct rt_ipc_object parent; /**< inherit from ipc_object */ //继承自IPC对象 void *msg_pool; /**< start address of message queue *///消息队列首地址 rt_uint16_t msg_size; /**< message size of each message */ //每条消息的最大长度
rt_uint16_t max_msgs; /**< max number of messages */ //消息队列最大可容纳的消息条数 rt_uint16_t entry; /**< index of messages in the queue *///当前消息队列中存在的消息条数 void *msg_queue_head; /**< list head */ //队首
void *msg_queue_tail; /**< list tail */ //队尾
void *msg_queue_free; /**< pointer indicated the free node of queue *///指向空闲队列
};
typedef struct rt_messagequeue *rt_mq_t;
#endif

以上是消息队列控制块的定义,那么消息队列内部包含的每条消息元素又是如何定义的呢?在src/ipc.c中定义:

struct rt_mq_message
{
struct rt_mq_message *next;//指向下一条消息元素
};
可能大家会有个疑问,怎么消息元素没有消息的具体数据内容呢?
其实上面这个消息元素只能算作是消息头,就好比短信的标题一般,真正内部跟随在这个消息头后面,一直到下一个消息头之前的所有内存中的数据就是消息的真正内容。rt-thread采用静态队列的方式来实现消息队列的IPC功能的。消息头只是用来做索引功能,通过它可以索引到下一个消息头的位置。如果大家还是有些不明白,那么可以先看看消息队列是如何初始化的,就会明白为什么会有这么一个消息头了。

二、消息队列相关接口:在src/ipc.c中:

创建消息队列:
rt_mq_t rt_mq_create(const char *name, //消息队列的名称
rt_size_t msg_size, //消息队列中每条消息的最大长度
rt_size_t max_msgs, //消息队列的最大容量
rt_uint8_t flag); //消息队列采用的等待方式(FIFO/PRIO)
创建消息队列时先创建一个消息队列对象控制块,然后给消息队列分配一块内存空间,组织成空闲消息链表,这块内存的大小等于[消息大小+消息头(用于链表连接)]与消息队列容量的乘积,接着再初始化消息队列,此时消息队列为空。 删除消息队列:
rt_err_t rt_mq_delete(rt_mq_t mq);
删除消息队列时,如果有线程被挂起在该消息队列等待队列上,则内核先唤醒挂起在该消息等待队列上的所有线程(返回值是 -RT_ERROR),然后再释放消息队列使用的内存,最后删除消息队列对象。
初始化消息队列:
rt_err_t rt_mq_init(rt_mq_t mq, //指向静态消息队列对象的句柄
const char *name, //消息队列的名称
void *msgpool, //用于存放消息的缓冲区首地址
rt_size_t msg_size, //消息队列中每条消息的最大长度
rt_size_t pool_size, //存放消息的缓冲区大小
rt_uint8_t flag); //消息队列采用的等待方式(FIFO/PRIO)
初始化消息队列时,该接口需要获得消息队列对象的句柄(即指向消息队列对象控制块的指针)、消息队列名、消息缓冲区指针、消息大小以及消息队列容量。消息队列初始化后所有消息都挂在空闲消息列表上,消息队列为空。 脱离消息队列:
rt_err_t rt_mq_detach(rt_mq_t mq);
使用该函数接口后,内核先唤醒所有挂在该消息等待队列对象上的线程(返回值是-RT_ERROR ),然后将该消息队列对象从内核对象管理器中删除。
发送消息:
rt_err_t rt_mq_send(rt_mq_t mq, void *buffer, rt_size_t size);
线程或者中断服务程序都可以给消息队列发送消息。当发送消息时,消息队列对象先从空闲消息链表上取下一个空闲消息块,把线程或者中断服务程序发送的消息内容复制到消息块上,然后把该消息块挂到消息队列的尾部。当且仅当空闲消息链表上有可用的空闲消息块时,发送者才能成功发送消息;当空闲消息链表上无可用消息块,说明消息队列已满,此时,发送消息的的线程或者中断程序会收到一个错误码(-RT_EFULL)。
发送消息时,发送者需指定发送到的消息队列的对象句柄(即指向消息队列控制块的指针),并且指定发送的消息内容以及消息大小。在发送一个普通消息之后,从空闲消息链表上取下的队首消息块被转移到了消息队列队尾。 发送紧急消息:
rt_err_t rt_mq_urgent(rt_mq_t mq, void *buffer, rt_size_t size);
发送紧急消息的过程与发送消息几乎一样,唯一的不同是,当发送紧急消息时,从空闲消息链表上取下来的队首消息块不是挂到消息队列的队尾,而是挂到消息队列的队首,这样接收者就能够优先接收到紧急消息,从而及时进行消息处理。 接收消息:
rt_err_t rt_mq_recv(rt_mq_t mq, //消息队列对象的句柄
void *buffer, //用于接收消息的数据块
rt_size_t size, //消息大小
rt_int32_t timeout); //指定的超时时间
当消息队列中有消息时,接收者才能接收消息,否则接收者会根据超时时间设置或挂起在消息队列的等待线程队列上,或直接返回。
接收消息时,接收者需指定存储消息的消息队列对象句柄,并且指定一个内存缓冲区,接收到的消息内容将被复制到该缓冲区里。此外,还需指定未能及时取到消息时的超时时间。
接收一个消息后消息队列上的队首消息被转移到了空闲消息链表的尾部。
控制消息队列:
rt_err_t rt_mq_control(rt_mq_t mq, rt_uint8_t cmd, void *arg);
只支持RT_IPC_CMD_RESET这一条命令,表示复位消息队列。

RT-thread内核之消息队列的更多相关文章

  1. Linux内核情景分析之消息队列

    早期的Unix通信只有管道与信号,管道的缺点: 所载送的信息是无格式的字节流,不知道分界线在哪,也没通信规范,另外缺乏控制手段,比如保温优先级,管道机制的大小只有1页,管道很容易写满而读取没有及时,发 ...

  2. System V 消息队列

    3.1 概述 消息队列结构: struct msqid_ds { struct ipc_perm msg_perm; //权限结构 struct msg *msg_first; //队列中第一个消息 ...

  3. Linux环境进程间通信(三):消息队列

    linux下进程间通信的几种主要手段: 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允 ...

  4. 四十九、进程间通信——System V IPC 之消息队列

    49.1 System V IPC 介绍 49.1.1 System V IPC 概述 UNIX 系统存在信号.管道和命名管道等基本进程间通讯机制 System V 引入了三种高级进程间通信机制 消息 ...

  5. IPC 进程间通信方式——消息队列

    消息队列 消息队列是内核中的一个链表 用户进程将数据传输到内核后,内核重新添加一些如用户ID.组ID.读写进程的ID和优先级等相关信息后并打包成一个数据包称为消息 允许一个或多个进程往消息队列中读写消 ...

  6. (转)Linux环境进程间通信----系统 V 消息队列列

    转:http://www.ibm.com/developerworks/cn/linux/l-ipc/part3/ 消息队列(也叫做报文队列)能够克服早期unix通信机制的一些缺点.作为早期unix通 ...

  7. 消息队列内核结构和msgget、msgctl 函数

    一.消息队列 1.消息队列提供了一个从一个进程向另外一个进程发送一块数据的方法 2.每个数据块都被认为是有一个类型,接收者进程接收的数据块可以有不同的类型值 3.消息队列与管道不同的是,消息队列是基于 ...

  8. μC/OS-III---I笔记9---任务等待多个内核对象和任务内建信号量与消息队列

    在一个任务等待多个内核对象在之前,信号量和消息队列的发布过程中都有等待多个内核对象判断的函数,所谓任务等待多个内核对象顾名思义就是一任务同时等待多个内核对象而被挂起,在USOC-III中一个任务等待多 ...

  9. 鸿蒙内核源码分析(消息队列篇) | 进程间如何异步传递大数据 | 百篇博客分析OpenHarmony源码 | v33.02

    百篇博客系列篇.本篇为: v33.xx 鸿蒙内核源码分析(消息队列篇) | 进程间如何异步传递大数据 | 51.c.h .o 进程通讯相关篇为: v26.xx 鸿蒙内核源码分析(自旋锁篇) | 自旋锁 ...

随机推荐

  1. 北京Uber优步司机奖励政策(12月19日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  2. 机器学习实战:KNN代码报错“AttributeError: 'dict' object has no attribute 'iteritems'”

    报错代码: sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True) 解决 ...

  3. 卸载Oracle 11g

    卸载oracle只需要执行deinstall.ba即可 运行.bat文件 按照提示步骤进行卸载 .bat文件所在目录需要手动删除,需要在程序管理器里面关掉Oracle的进程,在删除当前文件夹

  4. 在ubuntu trusty下安装python的rasterio库

    就这些吧.. apt-get update -y apt-get install -y software-properties-common add-apt-repository ppa:ubuntu ...

  5. 如何在Mac OS系统下搭建Java开发环境 配置Java环境变量

    1. 打开终端   在finder里面搜索(这台MAC)查找终端   2. 在cdlouiedeAir:~ cdlouie$(cdlouie是我的电脑用户名) 后面输入sudo vim /etc/pr ...

  6. 惊喜Skr人,Istio的创始人Shriram Rajagopalan手把手教你如何使用Istio

    Shriram与来自Google.Lyft.IBM和其他公司的社区贡献者们一起并肩作战,积极地向Istio和Envoy项目作贡献.同时,Shriram是IBM的Amalgam8项目的创始成员之一.目前 ...

  7. 2019年猪年海报PSD模板-第一部分

    14套精美猪年海报,免费猪年海报,下载地址:百度网盘,https://pan.baidu.com/s/1i7bIzPRTX0OMbHFWnqURWQ                        

  8. 「日常训练」Watering Flowers(Codeforces Round #340 Div.2 C)

    题意与分析 (CodeForces 617C) 题意是这样的:一个花圃中有若干花和两个喷泉,你可以调节水的压力使得两个喷泉各自分别以\(r_1\)和\(r_2\)为最远距离向外喷水.你需要调整\(r_ ...

  9. 制作一个App的完整流程是哪些

    APP开发流程其实并不复杂,但是对于客户来说,.一般移动APP开发都离不开UI设计师.前端开发.后端开发.测试专员.产品经理等,由于他们的工作性质都不一样,我们且先把APP软件开发项目分为三个阶段: ...

  10. Linux命令大全(非常全,史上最全)

    最近学习Linux,最大的体验就是它的很多东西都需要由命令来进行控制,下面是我总结的一些命令,供大家参考: 系统信息   arch 显示机器的处理器架构 uname -m 显示机器的处理器架构 una ...