FreeRTOS官方翻译文档——第二章 队列管理
2.1 概览
基于 FreeRTOS 的应用程序由一组独立的任务构成——每个任务都是具有独立权
限的小程序。这些独立的任务之间很可能会通过相互通信以提供有用的系统功能。
FreeRTOS 中所有的通信与同步机制都是基于队列实现的。
2.2队列的特性
数据存储
队列可以保存有限个具有确定长度的数据单元。队列可以保存的最大单元数目被称
为队列的“深度”。在队列创建时需要设定其深度和每个单元的大小。
通常情况下,队列被作为 FIFO(先进先出)使用,即数据由队列尾写入,从队列首读
出。当然,由队列首写入也是可能的。
往队列写入数据是通过字节拷贝把数据复制存储到队列中;从队列读出数据使得把
队列中的数据拷贝删除。 图 19 展现了队列的写入与读出过程,以及读写操作对队列中
数据的影响。
可被多任务存取
队列是具有自己独立权限的内核对象,并不属于或赋予任何任务。所有任务都可以
向同一队列写入和读出。一个队列由多方写入是经常的事,但由多方读出倒是很少遇到。
读队列时阻塞
当某个任务试图读一个队列时,其可以指定一个阻塞超时时间。在这段时间中,如
果队列为空,该任务将保持阻塞状态以等待队列数据有效。当其它任务或中断服务例程
往其等待的队列中写入了数据,该任务将自动由阻塞态转移为就绪态。当等待的时间超
过了指定的阻塞时间,即使队列中尚无有效数据,任务也会自动从阻塞态转移为就绪态。
由于队列可以被多个任务读取,所以对单个队列而言,也可能有多个任务处于阻塞
状态以等待队列数据有效。这种情况下,一旦队列数据有效,只会有一个任务会被解除
阻塞,这个任务就是所有等待任务中优先级最高的任务。而如果所有等待任务的优先级
相同,那么被解除阻塞的任务将是等待最久的任务。
写队列时阻塞
同读队列一样,任务也可以在写队列时指定一个阻塞超时时间。这个时间是当被写
队列已满时,任务进入阻塞态以等待队列空间有效的最长时间。
由于队列可以被多个任务写入,所以对单个队列而言,也可能有多个任务处于阻塞
状态以等待队列空间有效。这种情况下,一旦队列空间有效,只会有一个任务会被解除
阻塞,这个任务就是所有等待任务中优先级最高的任务。而如果所有等待任务的优先级
相同,那么被解除阻塞的任务将是等待最久的任务。
2.3 使用队列
xQueueCreate() API 函数
队列在使用前必须先被创建。
队列由声明为 xQueueHandle 的变量进行引用。 xQueueCreate()用于创建一个队
列,并返回一个 xQueueHandle 句柄以便于对其创建的队列进行引用。
当创建队列时, FreeRTOS 从堆空间中分配内存空间。分配的空间用于存储队列数
据结构本身以及队列中包含的数据单元。如果内存堆中没有足够的空间来创建队列,
xQueueCreate()将返回 NULL。
xQueueSendToBack() 与 xQueueSendToFront() API 函数
如同函数名字面意思所期望的一样, xQueueSendToBack()用于将数据发送到队列
尾;而 xQueueSendToFront()用于将数据发送到队列首。
xQueueSend()完全等同于 xQueueSendToBack()。
但 切 记 不 要 在 中 断 服 务 例 程 中 调 用 xQueueSendToFront() 或
xQueueSendToBack()。系统提供中断安全版本的 xQueueSendToFrontFromISR()与
xQueueSendToBackFromISR()用于在中断服务中实现相同的功能。
xQueueReceive()与 xQueuePeek() API 函数
xQueueReceive()用于从队列中接收(读取)数据单元。接收到的单元同时会从队列中删除。
xQueuePeek()也是从从队列中接收数据单元,不同的是并不从队列中删出接收到
的单元。 xQueuePeek()从队列首接收到数据后,不会修改队列中的数据,也不会改变
数据在队列中的存储序顺。
切记不要在中断服务例程中调用 xQueueRceive()和 xQueuePeek()。
uxQueueMessagesWaiting() API 函数
uxQueueMessagesWaiting()用于查询队列中当前有效数据单元个数。
切记不要在中断服务例程中调用 uxQueueMessagesWaiting()。应当在中断服务中
使用其中断安全版本 uxQueueMessagesWaitingFromISR()。
使用队列传递复合数据类型
一个任务从单个队列中接收来自多个发送源的数据是经常的事。通常接收方收到数
据后,需要知道数据的来源,并根据数据的来源决定下一步如何处理。一个简单的方式
就是利用队列传递结构体,结构体成员中就包含了数据信息和来源信息。 图 23 对这一方案进行了展现。
从图 23 中可以看出:
• 创建一个队列用于保存类型为 xData 的结构体数据单元。结构体成员包括了一个数
据值和表示数据含义的编码,两者合为一个消息可以一次性发送到队列。
• 中央控制任务用于完成主要的系统功能。 其必须对队列中传来的输入和其它系统状
态的改变作出响应。
• CAN 总线任务用于封装 CAN 总线的接口功能。当 CAN 总线任务收到并解码一个消
息后,其将把解码后的消息放到 xData 结构体中发往控制任务。结构体的 iMeaning
成员用于让中央控制任务知道这个数据是用来干什么的 — 从图中的描述可以看
出,这个数据表示电机速度。结构体的 iValue 成员可以让中央控制任务知道电机的
实际速度值。
• 人机接口(HMI)任务用于对所有的人机接口功能进行封装。设备操作员可能通过各种
方式进行命令输入和参数查询,人机接口任务需要对这些操作进行检测并解析。当
接收到一个新的命令后,人机接口任务通过 xData 结构将命令发送到中央控制任务。
结构体的 iMeaning 成员用于让中央控制任务知道这个数据是用来干什么的 — 从
图中的描述可以看出,这个数据表示一个新的参数设置。结构体的 iValue 成员可以
让中央控制任务知道具体的设置值。
工作于大型数据单元
如果队列存储的数据单元尺寸较大,那最好是利用队列来传递数据的指针而不是对
数据本身在队列上一字节一字节地拷贝进或拷贝出。传递指针无论是在处理速度上还是
内存空间利用上都更有效。但是,当你利用队列传递指针时,一定要十分小心地做到以下两点:
1. 指针指向的内存空间的所有权必须明确
当任务间通过指针共享内存时,应该从根本上保证所不会有任意两个任务同时
修改共享内存中的数据,或是以其它行为方式使得共享内存数据无效或产生一致性
问题。原则上,共享内存在其指针发送到队列之前,其内容只允许被发送任务访问;
共享内存指针从队列中被读出之后,其内容亦只允许被接收任务访问。
2. 指针指向的内存空间必须有效
如果指针指向的内存空间是动态分配的,只应该有一个任务负责对其进行内存
释放。当这段内存空间被释放之后,就不应该有任何一个任务再访问这段空间。
切忌用指针访问任务栈上分配的空间。因为当栈帧发生改变后,栈上的数据将不再有效。
这个时候,再回过头去看看上一篇随笔,为什么官方demo使用结构体指针,因为这样效率更高。
FreeRTOS官方翻译文档——第二章 队列管理的更多相关文章
- Prism 文档 第二章 初始化Prism应用程序
第二章 初始化Prism应用程序 本章将讨论为了使一个Pr ...
- Solidity 文档--第二章:安装 Solidity
安装Solidity 基于浏览器的Solidity 如果你只是想尝试一个使用Solidity的小合约,你不需要安装任何东西,只要访问基于浏览器的Solidity. 如果你想离线使用,你可以保存页面到本 ...
- FMDB官方使用文档-GCD的使用-提高性能(翻译)
FMDB官方使用文档-GCD的使用-提高性能(翻译) 发布于:2013-08-19 10:01阅读数:13395 由于FMDB是建立在SQLite的之上的,所以你至少也该把这篇文章从头到尾读一遍.与此 ...
- Umbraco官方技术文档 中文翻译
Umbraco 官方技术文档中文翻译 http://blog.csdn.net/u014183619/article/details/51919973 http://www.cnblogs.com/m ...
- Azkaban2官方配置文档
最近工作实在是太忙了,我把之前翻译的官方的文档先放上来吧,希望对大家有所帮助~ 介绍 Azkaban2新功能: 1.Web UI 2.简单工作流上传 3.更容易设置job的依赖关系 4.调度工作流 5 ...
- Java日志框架-Logback手册中文版以及官方配置文档教程
Logback手册中文版:(链接: https://pan.baidu.com/s/1bpMyasR 密码: 6u5c),虽然版本有点旧,但是大体意思差不多,先用中文版了解个大概,然后一切最新的配置以 ...
- Ext js-02 -官方API文档使用
官方API文档地址: http://docs.sencha.com/extjs/6.5.3/classic/Ext.html 打开网页如下: 1.选择所使用的Ext js版本,后面offline do ...
- Git教程(2)官方命令文档及常用命令表
http://www.cnblogs.com/angeldevil/archive/2013/11/26/3238470.html 1,官方命令文档 http://www.git-scm.com/do ...
- .Net 官方学习文档
.Net 官方学习文档:https://docs.microsoft.com/zh-cn/dotnet/articles/welcome
随机推荐
- Python下科学计算包numpy和SciPy的安装【原创】
Python下大多数工具包的安装都很简单,只需要执行 "python setup.py install"命令即可.然而,由于SciPy和numpy这两个科学计算包的依赖关系较多,安 ...
- go语言基础之格式化输出
1.fmt包的格式化输出输入 格式说明 格式 含义 %% 一个%字面量 %b 一个二进制整数值(基数为2),或者是一个(高级的)用科学计数法表示的指数为2的浮点数 %c 字符型.可以把输入的数字按照A ...
- microsoft visual c++与microsoft visual net 版本对应关系
7.1 -> 2003 8.0 -> 2005 9.0 -> 2008 10.0 -> 2010 11.0 -> 2012 12.0 -> 2013 14.0 -& ...
- JWT token心得
token的组成 token串的生成流程. token在客户端与服务器端的交互流程 Token的优点和思考 参考代码:核心代码使用参考,不是全部代码 JWT token的组成 头部(Header),格 ...
- [Unit Testing for Zombie] 06. Using Factory
FACTORIES Convert the zombies fixture to a Factory Girl Factory called :zombie. test/fixture/zombies ...
- async [ə'zɪŋk] 函数
ES7提供了async函数,使得异步操作变得更加方便.async函数是什么?一句话,async函数就是Generator函数的语法糖. 例1: var asyncFun = async functio ...
- vim中翻页的命令
整页翻页 ctrl-f ctrl-b f就是forword b就是backward 翻半页 ctrl-d ctlr-u d=down u=up 滚一行 ctrl-e ctrl-y zz 让光标所杂 ...
- HBase建立二级索引的一些解决方式
HBase的一级索引就是rowkey,我们仅仅能通过rowkey进行检索. 假设我们相对hbase里面列族的列列进行一些组合查询.就须要採用HBase的二级索引方案来进行多条件的查询. 常见的二级索引 ...
- 点击div和某些控件之外的地方隐藏div,点击div不隐藏。对象 click和document click冲突有关问题
帮朋友解决这个问题,我发现用以往想想像的方式来实现,貌似不太可行,所以从网上找了一些解决办法,进行优化,这篇比较详细,所以拿来备忘,另一方面也希望可以帮助需要的同学! 问题背景:jQuery事件问题! ...
- JDBC 获取被插入数据的主键ID值
除了用存储过程还有以下方法可以获取: static int create() throws SQLException { Connection conn = null; Pre ...