FreeRTOS的学习(七)——1.队列概念

23 篇文章 27 订阅

FreeRTOS的学习系列文章目录

FreeRTOS的学习(一)——STM32上的移植问题
FreeRTOS的学习(二)——任务优先级问题
FreeRTOS的学习(三)——中断机制
FreeRTOS的学习(四)——列表
FreeRTOS的学习(五)——系统延时
FreeRTOS的学习(六)——系统时钟
FreeRTOS的学习(七)——1.队列概念
FreeRTOS的学习(七)——2.队列入队源码分析
FreeRTOS的学习(七)——3.队列出队源码分析
FreeRTOS的学习(八)——1.二值信号量
FreeRTOS的学习(八)——2.计数型信号量
FreeRTOS的学习(八)——3.优先级翻转问题
FreeRTOS的学习(八)——4.互斥信号量
FreeRTOS的学习(九)——软件定时器
FreeRTOS的学习(十)——事件标志组
FreeRTOS的学习(十一)——任务通知



前言

队列在FreeRTOS中起到比较重要的作用,主要用于任务之间消息的传递,取代了裸机时代中的全局变量交互功能。队列的机制实现了任务与任务、任务与中断之间的消息传递。


1 FreeRTOS的队列

队列是为了任务与任务、任务与中断之间的通信而准备的,可以在任务与任务、任务与中断之间传递消息,队列中可以存储有限的、大小固定的数据项目。任务与任务、任务与中断之间要交流的数据保存在队列中,叫做队列项目。队列所能保存的最大数据项目数量叫做队列的长度,创建队列的时候会指定数据项目的大小和队列的长度。由于队列用来传递消息的,所以也称为消息队列。FreeRTOS 中的信号量的也是依据队列实现的!所以有必要深入的了解FreeRTOS 的队列。


2 队列概念分析

队列的代码组成和列表相似,由结构体组成,并有动态静态创建两种方法。
队列的概念本身接近于堆栈,可以简单理解成一个插入和取出的过程,但是在这个过程中又会涉及RTOS相关的概念,包括任务切换,列表等。

2.1 数据存储

通常队列采用先进先出(FIFO)的存储缓冲机制,也就是往队列发送数据的时候(也叫入队)永远都是发送到队列的尾部。,而从队列提取数据的时候(也叫出队)是从队列的头部提取的。但是也可以使用后进先出(LIFO) 的存储缓冲,FreeRTOS 中的队列也提供了 LIFO 的存储缓冲机制。

数据发送到队列中后,会被存储在队列中,这意味着队列存储的数据的原始值,而不是原数据的引用(即该数据的指针),这个传递过程也叫值传递。与UCOS不同,UCOS的消息队列采用引用传递,传递的是消息指针。但是这样做的缺点是采用引用传递的花消息就必须保持可见性,也就是消息内容必须有效,如此的话,例如函数的局部变量就存在会被随时删除的情况,但是采用引用传递的优势也很明显,可以大大减小数据传送到队列的时间。
另外值传递的优点是,在数据发送到队列后,原先存储数据的缓冲区可以被删除或者覆写,这样的话缓冲区就可以一直被重复使用。不过对于网络信息传递的情况往往需要传送大量的信息,那么势必会有很多时间用在消息队列传送的过程中,这种情况下,可以通过传递该组数据的指针地址即可,那么只要得到缓冲区的地址后就可以使用该地址为首的数据组。

2.2 出队阻塞

当任务尝试从一个队列中读取消息的时候可以指定一个阻塞时间,这个阻塞时间就是当任务从队列中读取消息无效的时候任务阻塞的时间。出队就是就从队列中读取消息,出队阻塞是针对从队列中读取消息的任务而言的。比如任务A用于处理串口接收到的数据,串口接收到数据以后就会放到队列 Q 中,任务 A从队列Q 中读取数据。但是如果此时队列Q 是空的,说明还没有数据,任务A这时候来读取的话肯定是获取不到任何东西,那该怎么办呢?任务A现在有三种选择,
一:不读数据直接结束这个读取的过程;
二:等待一段时间,也就是所谓的阻塞时间,在这段时间内读取到队列的数据就结束,反之,则等待阻塞时间到了之后就从延时列表进入就绪列表;
三:设置等待时间的为最大值portMAX_DELAY,也就是如果没有读取到数据就一直进入阻塞态等待,直到接收到数据为止。
选哪一个就是由这个阻塞时间决定的,这个阻塞时间单位是时钟节拍数。

2.3 入队阻塞

入队说的是向队列中发送消息,将消息加入到队列中。和出队阻塞一样,当一个任务向队列发送消息的话也可以设置阻塞时间。比如任务B向消息队列Q发送消息,但是此时队列Q是满的,那肯定是发送失败的。此时任务B就会遇到和上面任务A一样的问题,这两种情况的处理过程是类似的,只不过一个是向队列Q发送消息,一个是从队列Q读取消息而已。

2.4 队列操作过程图示

下面几幅图简单的演示了一下队列的入队和出队过程。

  1. 创建队列
    在这里插入图片描述
    上图中任务A要向任务B发送消息,这个消息是 x 变量的值。首先创建一个队列,并且指定队列的长度和每条消息的长度。这里我们创建了一个长度为 4 的队列,因为要传递的是x 值,而 x 是个 int 类型的变量,所以每条消息的长度就是 int 类型的长度,在 STM32中就是 4字节,即每条消息是 4 个字节的。
  2. 向队列发送第二个消息
    在这里插入图片描述
    上图中任务A又向队列发送了一个消息,即新的 x 的值,这里是 20。此时队列剩余长度为 2。
  3. 从队列中读取消息
    在这里插入图片描述
    上图中任务 B 从队列中读取消息,并将读取到的消息值赋值给 y,这样 y 就等于 10了。任务B 从队列中读取消息完成以后可以选择清除掉这个消息或者不清除。当选择清除这个消息的话其他任务或中断就不能获取这个消息了,而且队列剩余大小就会加一,变成 3。如果不清除的话其他任务或中断也可以获取这个消息,而队列剩余大小依旧是 2。

3 文章参考

正点原子:STM32F1 FreeRTOS开发手册

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LEODWL

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值