目录
- FreeRTOS学习第9篇--队列介绍
- 1. 数据传输的方法
- 1.1 任务之间如何传输数据
- 1.2 队列的本质
- 2. 队列的工作原理和实现
- 2.1 创建队列
- 2.2 向队列发送数据
- 2.3 从队列接收数据
- 3. 使用队列进行任务间的通信
- 3.1 通信示例
- 3.2 同步示例
- 结论
FreeRTOS学习第9篇–队列介绍
本文目标:FreeRTOS学习第9篇–队列介绍
按照本文的描述,理解操作系统中的队列
本文实验条件:理论学习篇
1. 数据传输的方法
1.1 任务之间如何传输数据
多种方法比较:
数据个数 | 互斥措施 | 阻塞-唤醒 | 使用场景 | |
---|---|---|---|---|
全局变量 | 1 | 无 | 无 | 一读一写 |
环形缓冲区 | 多个 | 无 | 无 | 一读一写 |
队列 | 多个 | 有 | 有 | 多读多写 |
初学感觉消息队列挺麻烦,搞个全局数组不是更简单,其实不然。在裸机编程时,使用全局数组的确比较方便,但是在加上 RTOS 后就是另一种情况了。相比消息队列,使用全局数组主要有如下四个问题:
1.使用消息队列可以让 RTOS 内核有效地管理任务,而全局数组是无法做到的,任务的超时等机制需要用户自己去实现。
2.使用了全局数组就要防止多任务的访问冲突,而使用消息队列则处理好了这个问题,用户无需担心。
3.使用消息队列可以有效地解决中断服务程序与任务之间消息传递的问题。
4.FIFO 机制更有利于数据的处理。
1.2 队列的本质
队列中,数据的读写本质就是环形缓冲区,在这个基础上增加了互斥措施、阻塞-唤醒机制。
如果这个队列不传输数据,只调整"数据个数",它就是信号量(semaphore)。
如果信号量中,限定"数据个数"最大值为1,它就是互斥量(mutex)。
接下来,我们将继续深入探讨队列的工作原理、实现方式以及如何在FreeRTOS中使用队列进行任务间的同步和通信。
2. 队列的工作原理和实现
队列(Queue)是一种先进先出(FIFO,First In First Out)的数据结构,它允许在一端(rear)添加数据,在另一端(front)移除数据。在FreeRTOS中,队列不仅用于数据传输,还可以用作任务同步机制。FreeRTOS队列传递的是实际数据,并不是数据地址。
2.1 创建队列
在FreeRTOS中,队列是通过调用xQueueCreate()
函数创建的。此函数需要两个参数:队列可以存储的最大元素数量和每个元素的大小。
c复制QueueHandle_t xQueueCreate( UBaseType_t uxQueueLength, UBaseType_t uxItemSize );
创建成功后,函数返回一个队列句柄(QueueHandle_t
),通过这个句柄可以访问队列。如果创建失败,返回NULL
。
2.2 向队列发送数据
通过xQueueSend()
、xQueueSendToFront()
、xQueueSendToBack()
和xQueueSendOverwrite()
函数可以向队列发送数据。这些函数允许在不同的场景下发送数据,比如添加到队列的前面或后面,或者覆盖队列中的现有数据。
BaseType_t xQueueSend( QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait );
2.3 从队列接收数据
通过xQueueReceive()
函数从队列接收数据。调用此函数时,如果队列为空,则任务可以选择阻塞等待直到数据可用。
BaseType_t xQueueReceive( QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait );
3. 使用队列进行任务间的通信
队列是实现任务间通信的强大工具。它们允许任务以线程安全的方式交换信息,而不必担心数据损坏或竞态条件。
3.1 通信示例
考虑一个生产者-消费者场景,生产者任务创建数据,消费者任务处理数据。这里,队列充当生产者和消费者之间的桥梁。
- 生产者任务将数据发送到队列。
- 消费者任务等待队列中的数据,接收后进行处理。
3.2 同步示例
队列也可以用于任务同步。例如,一个任务可能需要等待另一个任务完成特定工作后才能继续。这可以通过发送和接收特定的同步消息(或信号)来实现。
结论
理解和使用队列是掌握FreeRTOS中任务间通信和同步的关键。通过本文的介绍,您应该能够理解队列的基本概念、如何创建和使用队列以及如何利用队列在任务间传递数据和信号。实践中,灵活运用队列不仅可以解决复杂的同步问题,还能提升系统的稳定性和响应速度。