RT-thread内核之消息队列
一、消息队列控制块:在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内核之消息队列的更多相关文章
- Linux内核情景分析之消息队列
早期的Unix通信只有管道与信号,管道的缺点: 所载送的信息是无格式的字节流,不知道分界线在哪,也没通信规范,另外缺乏控制手段,比如保温优先级,管道机制的大小只有1页,管道很容易写满而读取没有及时,发 ...
- System V 消息队列
3.1 概述 消息队列结构: struct msqid_ds { struct ipc_perm msg_perm; //权限结构 struct msg *msg_first; //队列中第一个消息 ...
- Linux环境进程间通信(三):消息队列
linux下进程间通信的几种主要手段: 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允 ...
- 四十九、进程间通信——System V IPC 之消息队列
49.1 System V IPC 介绍 49.1.1 System V IPC 概述 UNIX 系统存在信号.管道和命名管道等基本进程间通讯机制 System V 引入了三种高级进程间通信机制 消息 ...
- IPC 进程间通信方式——消息队列
消息队列 消息队列是内核中的一个链表 用户进程将数据传输到内核后,内核重新添加一些如用户ID.组ID.读写进程的ID和优先级等相关信息后并打包成一个数据包称为消息 允许一个或多个进程往消息队列中读写消 ...
- (转)Linux环境进程间通信----系统 V 消息队列列
转:http://www.ibm.com/developerworks/cn/linux/l-ipc/part3/ 消息队列(也叫做报文队列)能够克服早期unix通信机制的一些缺点.作为早期unix通 ...
- 消息队列内核结构和msgget、msgctl 函数
一.消息队列 1.消息队列提供了一个从一个进程向另外一个进程发送一块数据的方法 2.每个数据块都被认为是有一个类型,接收者进程接收的数据块可以有不同的类型值 3.消息队列与管道不同的是,消息队列是基于 ...
- μC/OS-III---I笔记9---任务等待多个内核对象和任务内建信号量与消息队列
在一个任务等待多个内核对象在之前,信号量和消息队列的发布过程中都有等待多个内核对象判断的函数,所谓任务等待多个内核对象顾名思义就是一任务同时等待多个内核对象而被挂起,在USOC-III中一个任务等待多 ...
- 鸿蒙内核源码分析(消息队列篇) | 进程间如何异步传递大数据 | 百篇博客分析OpenHarmony源码 | v33.02
百篇博客系列篇.本篇为: v33.xx 鸿蒙内核源码分析(消息队列篇) | 进程间如何异步传递大数据 | 51.c.h .o 进程通讯相关篇为: v26.xx 鸿蒙内核源码分析(自旋锁篇) | 自旋锁 ...
随机推荐
- WPF 应用程序资源、内容和数据文件
MSDN相关介绍: http://msdn.microsoft.com/zh-cn/library/aa970494(v=vs.100).aspx 内容文件(Content Files)内容文件简单的 ...
- 北京Uber优步司机奖励政策(3月22日)
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...
- MySql 使用explain分析查询
今天写了个慢到哭的查询,想用explain分析下执行计划,后来发现explain也是有局限性的: EXPLAIN不会告诉你关于触发器.存储过程的信息或用户自定义函数对查询的影响情况 •EXPLAIN不 ...
- 【Hadoop】Seondary NameNode不是备份NameNode!!
昨天和舍友聊天时无意中提起Secondary NameNode,他说这是备用NameNode.我当时就有点疑惑..之后查阅了相关资料和博客,算是基本理解了什么是Secondary NameNode. ...
- Java: Replace a string from multiple replaced strings to multiple substitutes
Provide helper methods to replace a string from multiple replaced strings to multiple substitutes im ...
- 软件测试的基础-摘自《selenium实践-基于电子商务平台》
软件测试的方法 一.等价类划分法 等价类划分法是把所有可能的输入数据,即程序的输入域划分成若干部分(子集),然后从每一个子集中选取少量具有代表性的数据作为测试用例. 有两种不同的情况:有效等价和无效等 ...
- 怎样用Eclipse将Java源代码生成可执行文件[转]
eclipse将java源代码生成jar可执行文件 用eclipse做了一个web项目的自动化测试,自己用的时候倒是很方便,打开eclipse直接运行即可,但是分享给其他小伙伴用的时候就不太方便,希望 ...
- sqlalchemy 转json 的几种常用方式
sqlalchemy 转json 的几种常用方式 # -*- coding:utf-8 -*- import datetime from flask import Flask, json, jsoni ...
- Tensorflow中使用tfrecord方式读取数据-深度学习-周振洋
本博客默认读者对神经网络与Tensorflow有一定了解,对其中的一些术语不再做具体解释.并且本博客主要以图片数据为例进行介绍,如有错误,敬请斧正. 使用Tensorflow训练神经网络时,我们可以用 ...
- lvs+keepalived详解
常用软件安装及使用目录 资源链接:https://pan.baidu.com/s/15rFjO-EnTOyiTM7YRkbxuA 网盘分享的文件在此 官网:http://www.linuxvir ...