FreeRTOS消息队列详解第一讲(全网最全)——消息队列概述
一、队列简介
队列是为了任务与任务、任务与中断之间的通信而准备的,可以在任务与任务、任务与中断之间传递消息,队列中可以存储有限的、大小固定的数据项目。 任务与任务、任务与中断之间要交流的数据保存在队列中,叫做队列项目。队列所能保存的最大数据项目数量叫做队列的长度,创建队列的时候会指定数据项目的大小和队列的长度。由于队列用来传递消息的,所以也称为消息队列。FreeRTOS中的信号量的也是依据队列实现的!所以有必要深入的了解FreeRTOS的队列。
1、数据存储
通常队列采用先进先出(FIFO)的存储缓冲机制,也就是往队列发送数据的时候(也叫入队)永远都是发送到队列的尾部,而从队列提取数据的时候(也叫出队)是从队列的头部提取的。但是也可以使用LIFO的存储缓冲,也就是后进先出,FreeRTOS中的队列也提供了LIFO的存储缓冲机制。数据发送到队列中会导致数据拷贝,也就是将要发送的数据拷贝到队列中,这就意味着在队列中存储的是数据的原始值,而不是原数据的引用(即只传递数据的指针),这个也叫做值传递。UCOS的消息队列采用的是引用传递,传递的是消息指针采用引用传递的话消息内容就必须一直保持可见性,也就是消息内容必须有效,那么局部变量这种可能会随时被删掉的东西就不能用来传递消息,但是采用引用传递会节省时间啊!因为不用进行数据拷贝。采用值传递的话虽然会导致数据拷贝,会浪费一点时间,但是一旦将消息发送到队列中原始的数据缓冲区就可以删除掉或者覆写,这样的话这些缓冲区就可以被重复的使用。(注意:FreeRTOS也可以实现引用传递,只需要传递地址即可)
2、多任务访问
队列不是属于某个特定的任务的,任何任务都可以向队列中发送消息,或者从队列中提取消息。
3、出队阻塞
当任务尝试从一个队列中读取消息的时候可以指定一个阻塞时间,这个阻塞时间就是当任务从队列中读取消息无效的时候任务阻塞的时间。出队就是就从队列中读取消息,出队阻塞是针对从队列中读取消息的任务而言的。比如任务A用于处理串口接收到的数据,串口接收到数
据以后就会放到队列Q中,任务A从队列Q中读取数据。但是如果此时队列Q是空的,说明还没有数据,任务A这时候来读取的话肯定是获取不到任何东西,那该怎么办呢?任务A现在有三种选择,一:二话不说扭头就走,二:要不我在等等吧,等一会看看,说不定一会就有数据了,三:死等,死也要等到你有数据!选哪一个就是由这个阻塞时间决定的,这个阻塞时间单位是时钟节拍数。
①、阻塞时间为0的话就是不阻塞,没有数据的话就马上返回任务继续执行接下来的代码,对应第一种选择。
②、如果阻塞时间为0~portMAX_DELAY,当任务没有从队列中获取到消息的话就进入阻塞态,阻塞时间指定了任务进入阻塞态的时间,当阻塞时间到了以后还没有接收到数据的话就退出阻塞态,返回任务接着运行下面的代码。如果在阻塞时间内接收到了数据就立即返回,执行任务中下面的代码,这种情况对应第二种选择。
③、当阻塞时间设置为portMAX_DELAY的话,任务就会一直进入阻塞态等待,直到接收到数据为止!这个就是第三种选择。
4、入队阻塞
入队说的是向队列中发送消息,将消息加入到队列中。和出队阻塞一样,当一个任务向队列发送消息的话也可以设置阻塞时间。比如任务B向消息队列Q发送消息,但是此时队列Q是满的,那肯定是发送失败的。此时任务B就会遇到和上面任务A一样的问题,这两种情况的处理过程是类似的,只不过一个是向队列Q发送消息,一个是从队列Q读取消息而已。
5、队列操作过程
- 创建队列
任务A要向任务B发送消息,这个消息是x变量的值。首先创建一个队列,并且指定队列的长度和每条消息的长度。这里我们创建了一个长度为4的队列,因为要传递的是x值,而x是个int类型的变量,所以每条消息的长度就是int类型的长度,在STM32中就是4字节,即每条消息是4个字节的。 - 向队列发送第一个消息
任务A的变量x值为10,将这个值发送到消息队列中。此时队列剩余长度就是3了。前面说了向队列中发送消息是采用拷贝的方式,所以一旦消息发送完成变量x就可以再次被使用,赋其他的值。 - 向队列发送第二个消息
任务A又向队列发送了一个消息,即新的x的值,这里是20。此时队列剩余长度为2。 - 从队列中读取消息
任务B从队列中读取消息,并将读取到的消息值赋值给y,这样y就等于10了。任务B从队列中读取消息完成以后可以选择清除掉这个消息或者不清除。当选择清除这个消息的话其他任务或中断就不能获取这个消息了,而且队列剩余大小就会加一,变成3。如果不清除的话其他任务或中断也可以获取这个消息,而队列剩余大小依旧是2。
二、队列结构体
有一个结构体用于描述队列,叫做Queue_t,在queue.c中定义:
typedef struct QueueDefinition
{int8_t *pcHead; //指向队列存储区开始地址int8_t *pcTail; //指向队列存储区最后一个字节 int8_t *pcWriteTo;//指向存储区中下一个空闲区域union {int8_t *pcReadFrom;//当用作队列的时候指向最后一个出队的队列项首地址 UBaseType_t uxRecursiveCallCount;//当用作递归互斥量的时候用来记录递归互斥量被调用的次数} u;List_t xTasksWaitingToSend;//等待发送任务列表,那些因为队列满导致入队失败而进入阻塞态的任务就会挂在这个列表上List_t xTasksWaitingToReceive;//等待接受任务列表,那些因为队列空导致出队失败而进入阻塞态的任务就会挂到此列表上volatile UBaseType_t uxMessagesWaiting;//队列中当前队列项数量,也就是消息数UBaseType_t uxLength;//创建队列时指定的队列长度,也就是队列中最大允许的队列项数量UBaseType_t uxItemSize; //创建队列时指定的每个队列项最大长度,单位字节volatile int8_t cRxLock;//当队列上锁以后用来统计从队列中接收到的队列项数量,也就是出队的队列项数量 volatile int8_t cTxLock;//当队列上锁以后用来统计发送到队列中的队列项数量,也就是入队的队列项数量 #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )uint8_t ucStaticallyAllocated; //如果使用静态存储的话此字段设置为pdTURE#endif#if ( configUSE_QUEUE_SETS == 1 )//队列集相关宏struct QueueDefinition *pxQueueSetContainer;#endif#if ( configUSE_TRACE_FACILITY == 1 )//跟踪调试相关宏UBaseType_t uxQueueNumber;uint8_t ucQueueType;#endif} xQUEUE;
typedef xQUEUE Queue_t;
队列的基础知识就讲解到这里啦!下一讲将会讲解队列API的使用。
FreeRTOS消息队列详解第一讲(全网最全)——消息队列概述相关推荐
- C#:Krypton控件使用方法详解(第一讲) —— kryptonButton
今天介绍的Krypton控件中的kryptonButton,这个控件和VS中带的Button控件还是不一样的,下面介绍这个控件. 这个控件的属性如下图所示: 首先要介绍这个kryptonButton控 ...
- 均线系统之详解 —— 第一讲
均线-我们主要的指标 任何股票软件安装后,我们首先看到的就是K线与均线组合的主图.可见,均线系统是多么的普遍和实用.但真正用好均线系统的有多少呢?为什么我们总是到处寻找更好的指标?总是觉得还有更容易, ...
- JavaScript数据结构与算法——队列详解(下)
接下来会借助本人另一篇文章JavaScript数据结构与算法--队列详解(上)中实现的队列类及其方法实现一个应用. 配对问题 需求分析:在一个文件中保存着一份男女混合的数据,名称前以B开头表示男士,以 ...
- linux fq队列,QOS各种队列详解(FIFO,FQ,CBWFQ,PQ).doc
QOS各种队列详解(FIFO,FQ,CBWFQ,PQ) QOS各种队列详解(FIFO,FQ,CBWFQ,PQ) 对于拥塞管理,一般采用队列技术,使用一个队列算法对流量进行分类,之后用某种优先级别算法将 ...
- MQ消息队列详解、四大MQ的优缺点分析
MQ消息队列详解.四大MQ的优缺点分析 前言 面试题切入 面试官心理分析 面试题剖析 ①为什么要使用MQ 系统解耦 异步调用 流量削峰 消息队列的优缺点 四大主流MQ(kafka.ActiveMQ.R ...
- linux如何查看kafka消息队列,kafka以及消息队列详解
kafka以及消息队列详解 Kafka 是LinkedIn 开发的一个高性能.分布式的消息系统. 用途:广泛用于日志收集.流式数据处理.在线和离线消息分发等场景. 1. Kafka 将消息流按Topi ...
- 窗口发送消息参数详解
窗口发送消息参数详解 // 窗口.发送消息 函数功能: 将指定的消息发送到一个窗口,同win32 api 里面的SendMessage等同的效果 中文函数原型: 发送消息(hwnd,msg ...
- Windows 窗口发送消息参数详解
窗口发送消息参数详解 // 窗口.发送消息 函数功能: 将指定的消息发送到一个窗口,同win32 api 里面的SendMessage等同的效果中文函数原型: 发送消息(hwnd,msg,wparam ...
- 转:Java 7 种阻塞队列详解
转自: Java 7 种阻塞队列详解 - 云+社区 - 腾讯云队列(Queue)是一种经常使用的集合.Queue 实际上是实现了一个先进先出(FIFO:First In First Out)的有序表. ...
- (08)System Verilog 队列详解
(08)System Verilog 队列详解 1.1 目录 1)目录 2)FPGA简介 3)System Verilog简介 4)System Verilog 队列详解 5)结语 1.2 FPGA简 ...
最新文章
- Spring基础专题——第七章(持久层整合)
- linux系统编程快速定位头文件的技巧之强大的grep命令
- centos下ftp接受/发送文件
- CTFshow 反序列化 web259
- 2020-11-6(简述html)
- 授予数据库账号dba权限_从自建Oracle迁移至云原生数据仓库AnalyticDB PostgreSQL
- 为什么视频压缩如此重要
- dropMenu----简单的下拉菜单生成器
- 第一阶段SCRUM冲刺 08
- html css布局 慕课,html5和css3学习 Header实现CSS的布局
- Python-进阶-装饰器小结
- 学习python: 常见面试题总结
- 固高运动控制卡学习6 --编码器
- 2019年畅销好书大盘点,有你喜欢的书吗?
- cad如何多选对象_cad如何多选?在CAD里为什么只能选中一个对象,而不能累加选择多个对象?...
- win7计算机不在桌面了,怎么办Win7系统开机后不显示桌面
- 2016 西班牙 国家德比(西甲31轮)
- 【字符串】字符串逆序
- 如何让函数只执行一次
- Markdown学习之(2)-绘制表格和流程图