首页 > 其他分享 >《Mastering the FreeRTOS Real Time Kernel》读书笔记(3)队列管理

《Mastering the FreeRTOS Real Time Kernel》读书笔记(3)队列管理

时间:2023-10-13 10:48:00浏览次数:37  
标签:Real Kernel 读取 读书笔记 队列 阻塞 任务 xQueue 数据

4.队列管理

队列,在一些系统中被称为消息队列,可以理解为信息中转站。是任务和任务,任务和中断之间可以互相读和写的一个共享空间。

4.2 队列的特征

存储数据

队列本质上是一个先进先出的缓冲区(FIFO),所以可以存储一定容量的数据。
有两种方式可以实现FIFO队列:
1.将发送给队列的数据复制到队列中,队列中存储的是真实的数据。
2.仅将数据的指针存储在队列中。

FreeRTOS使用第一种方式,因为第一种方式更加稳定,它不用考虑2中,数据被改动或者消失的情况。当然,如果数据的确比较大,也可以将它的指针存入队列,但是一定要保证这些数据的有效性。

队列的存在一方面也是为了更好的管理数据和内存,其不会让一些无关任务随意地访问该数据。

支持多任务访问

任何被允许访问队列的任务都可以访问队列。在在实践中,一个队列有多个写入程序是很常见的,但一个队列中有多个读取程序就不那么常见了,这可能会导致先出的信息存在歧义而导致死循环。

队列被读取时的阻塞机制

当有任务需要读取队列时,队列可以根据队列内信息的多寡,对任务的状态进行设置。当队列为空,该任务被设置为阻塞状态,当队列内有数据可用,该任务被设置为就绪。

多任务读取时的优先级安排:一个队列可能会阻止多个任务等待数据。在这种情况下,当数据可用时,只有一个任务将被取消阻止。未阻止的任务将始终是等待数据的优先级最高的任务。如果被阻止的任务具有相同的优先级,则等待数据时间最长的任务将被取消阻止。

队列被写入时的阻塞机制

队列写入时的阻塞就像从队列读取时一样,任务可以在写入队列时指定阻塞时间。在这种情况下,阻塞时间是指如果队列已满,则任务应保持在“阻塞”状态以等待队列上的空间变为可用的最长时间。
队列可以有多个写入程序,因此一个完整的队列可能会阻塞多个任务等待完成发送操作。在这种情况下,当队列上的空间变为可用时,只有一个任务将被取消阻塞。未阻塞的任务将始终是等待空间的优先级最高的任务。如果被阻塞的任务具有相同的优先级,则等待空间最长的任务将被取消阻塞。

4.3 使用一个队列

QueueHandle_t xQueueCreate( UBaseType_t uxQueueLength, UBaseType_t uxItemSize );

FreeRTOS V9.0.0还包括xQueueCreateStatic()函数,该函数在编译时分配静态创建队列所需的内存。
1.uxQueueLength:可以容纳的最大数据数。
2.uxltemSize:队列的位宽,每个数据的大小(以字节为单位)。
3.返回值:如果返回NULL,因为没有足够的堆内存可供FreeRTOS分配队列数据结构和存储区域。返回的非NULL值表示队列已成功创建。返回的值应存储为创建的队列的句柄。
创建队列后,可以使用xQueueReset()API函数将队列返回到其原始空状态。

发送数据

xQueueSendToBack()用于将数据发送到队列的后部(尾部),xQueQueueSendtoFront()用于向队列的前部(头部)发送数据。xQueueSend()等效于xQueueSendToBack(),并且与之完全相同。

注意:在中断中使用的是中断安全版本xQueueSendToFrontFromISR()和xQueueSendToBackFromISR()。

BaseType_t xQueueSendToFront( QueueHandle_t xQueue,
                              const void * pvItemToQueue,
                              TickType_t xTicksToWait );

BaseType_t xQueueSendToBack( QueueHandle_t xQueue,
                              const void * pvItemToQueue,
                              TickType_t xTicksToWait );

1.xQueue(队列名字):将数据发送(写入)到的队列的句柄。队列句柄将从用于创建队列的xQueueCreate调用中返回。
2.pvltemToQueue:指向要复制到队列中的数据的指针。队列可以容纳的每个项目的大小是在创建队列时设置的,因此这许多字节将从pvItemToQueue复制到队列存储区域中。
3.xTicksToWait:任务应保持在“阻塞”状态以等待队列上的空间变为可用的最长时间。
4.返回值:
(1)只有当数据成功发送到队列时,才会返回pdPASS。如果指定了块时间(xTicksToWait不为零),则在函数返回之前,调用任务可能被置于“阻塞”状态,以等待队列中的空间变为可用,但在块时间到期之前,数据已成功写入队列。
(2)如果由于队列已满而无法将数据写入队列,则将返回errQUEUE_FULL。如果指定了块时间(xTicksToWait不为零),则调用任务将被置于“阻塞”状态,以等待另一个任务或中断在队列中腾出空间,但指定的块时间在此之前已过期。

接收数据

同上,分为普通版本和中断安全版本

BaseType_t xQueueReceive( QueueHandle_t xQueue,
                          void * const pvBuffer,
                          TickType_t xTicksToWait );

参数设置基本同上。

查询队列内数据数量

同上,分为普通版本和中断安全版本

UBaseType_t uxQueueMessagesWaiting( QueueHandle_t xQueue );

xQueue:同上

例子10:二发一收的抢占机制

1.Receiver任务首先运行,因为它具有最高优先级。它尝试从队列中读取。队列为空,因此接收器进入阻止状态以等待数据可用。发送器2在接收器被阻止后运行。
2.之后由于发射器2和发射器1是相同优先级,所以他们会交替运行。接收器也可以交替接收。

4.4 一个队列接受多种数据源

一个简单的设计解决方案是使用单个队列来传输结构体,该结构体的字段中包含数据值和数据源。
例子11:接收器通过发送数据包中的数据源,来判断数据来源。
具体使用还需要结合实际情况,可以实现更多效果。

4.5 传输大数据或可变大小数据

1.数据过大,不易拷贝到队列:直接发送数据的指针。但是一定要保证该指针有效,该指针指向的数据是有效的。
2.对于可变数据(不定长)的接受与处理:之前的两种强大的方法,向队列发送结构以及向队列发送指针。将这些技术相结合,可以使任务使用单个队列从任何数据源接收任何数据类型。
FreeRTOS+TCPTCP/IP堆栈的实现提供了一个如何实现这一点的实际示例。在自己的任务中运行的TCP/IP堆栈必须处理来自许多不同来源的事件。不同的事件类型与不同类型和长度的数据相关联。在TCP/IP任务之外发生的所有事件都由IPStackEvent_t类型的结构描述,并发送到队列上的TCP/IP任务。

4.6 从多个队列接受数据(队列集)

可以使用“队列集”(queue set)。队列集允许任务从多个队列接收数据,而无需任务依次轮询每个队列以确定哪个队列(如果有的话)包含数据。
但是,使用队列集从多个源接收数据的设计不那么整洁,也不那么高效。因此,建议只有在设计约束绝对需要使用队列集的情况下才使用队列集。
1.正在创建队列集。
2.将队列添加到集合中。信号量也可以添加到队列集中。信号量在这本书后面有描述。
3.从队列集合中读取以确定集合中的哪些队列包含数据。当作为集合成员的队列接收数据时,接收队列的句柄将发送到队列集合,并在任务调用从队列集读取的函数时返回。因此,如果从队列集返回队列句柄,则该句柄引用的队列包含数据,然后任务可以直接从队列中读取。
通过在FreeRTOSConfig.h中将configUSE_Queue_SETS编译时配置常量设置为1,可以启用队列集功能。
队列集相关函数和例子12不予介绍,请自行查询Queue Set相关内容。

4.7 使用队列构建一个“邮箱”

“邮箱”在不同的RTOS中意味着不同的东西。在本书中,“邮箱”一词用于指长度为1的队列。“邮箱”使用方法如下:
邮箱用于保存任何任务或任何中断服务例程都可以读取的数据。数据不会通过邮箱,而是保留在邮箱中,直到覆盖为止。发件人将覆盖邮箱中的值。接收器从邮箱中读取值,但不会从邮箱中删除该值。

xQueueOverwrite()

BaseType_t xQueueOverwrite( QueueHandle_t xQueue, const void * pvItemToQueue );

与xQueueSendToBack()API函数一样,xQueueOverwrite()API函数将数据发送到队列。与xQueueSendToBack()不同,如果队列已满,则xQueueOverwrite()将覆盖队列中已存在的数据。xQueueOverwrite()只能用于长度为1的队列。如果队列已满,则该限制避免了函数实现对覆盖队列中的哪一项做出任意决定的需要。
1.xQueue:xQueueCreate()调用中返回的队列句柄。
2.pvltemToQueue:指向要复制到队列中的数据的指针。

xQueuePeek()

xQueuePeek()用于接收(读取)队列中的项目,而不从队列中删除该项目。

BaseType_t xQueuePeek( QueueHandle_t xQueue,
                        void * const pvBuffer,
                        TickType_t xTicksToWait );

参数设置与xQueueReceive()类似。

标签:Real,Kernel,读取,读书笔记,队列,阻塞,任务,xQueue,数据
From: https://www.cnblogs.com/HYBZ/p/17758987.html

相关文章

  • Dear Reality推出SPATIAL CONNECT for Wwise——XR音频制作新高度
    (DearReality演示视频截图)游戏混音的未来在头戴式设备中DearReality推出SPATIALCONNECTforWwise——XR音频制作新高度沉浸式音频专家DearReality宣布启动“SPATIALCONNECTforWwise”项目,该项目旨在支持游戏音频设计师在交互式VR和AR音频制作中实现完全沉浸式工作。这项......
  • 为什么我们需要不断的开发不同的机器学习模型 —— Do we Need Hundreds of Classifie
        ==========================================  论文:《DoweNeedHundredsofClassifierstoSolveRealWorldClassificationProblems?》  论文地址:https://jmlr.org/papers/volume15/delgado14a/delgado14a.pdf        =========......
  • English conversation in real life
    常见疑问句Whatdoyoufeel?你感觉如何Doyouthinkyoucanmakeitsitdown?Yes,Ishouldmakeittothebench.你认为你能走到那里坐下来吗?是的,我应该能走到长椅那里。Whatdoyoufancy?你想做什么?Whatareyouthinking?你有什么想法?I'vegotanidea;howabo......
  • Semantic Kernel .NET SDK 的 v1.0.0 Beta1 发布
    介绍SemanticKernel(SK)是一个开源的将大型语言模型(LLM)与流行的编程语言相结合的SDK,Microsoft将SemanticKernel(简称SK)称为轻量级SDK,结合了OpenAI,AzureOpenAI和HuggingFace等AILLM的集成。它使开发人员能够通过编排AI组件并将其与现有代码集成来创建AI应用。SDK提供对J......
  • 《Mastering the FreeRTOS Real Time Kernel》读书笔记(2)任务管理
    3.任务管理如何为每个任务分配处理时间,如何选择在任何给定时间执行何种任务,任务优先级,任务状态。3.2任务功能每个任务必须返回void,并接受一个void类型指针。这些任务一般会写成一个无限循环,由内核来调度,完成任务安排,创建和删除。3.3顶层任务状态由于一般单片机处理器为单核......
  • 《Mastering the FreeRTOS Real Time Kernel》读书笔记(1)堆内存管理
    这是161204的版本,不完全覆盖目前最新版本的内核。0.关于freeRTOS首先提出了了在小型嵌入式系统中为何需要多任务管理的问题,介绍了freeRTOS的用途。然后开始做广告,吹了一波freeRTOS的好处。其中要注意一些关键的名词:任务优先级分配、任务通知、队列、信号量、互斥锁、软定时器、......
  • 《流畅的Python》 读书笔记 第二章数据结构(2) 231011
    2.5对序列使用+和*通常+号两侧的序列由相同类型的数据所构成,在拼接的过程中,两个被操作的序列都不会被修改,Python会新建一个包含同样类型数据的序列来作为拼接的结果+和*都遵循这个规律,不修改原有的操作对象,而是构建一个全新的序列l1=[1,2,3]l2=[4,5,6]print(id(l......
  • 《架构师之路:软件架构之美》第四,五章读书笔记
    第四章:系统可伸缩性的重要性第四章讨论了系统可伸缩性的重要性。在现代软件开发中,可伸缩性是一个关键概念,它涉及到系统在不同负载下的性能表现。以下是一些关键观点:可伸缩性是应对用户增长和数据量增加的关键。一个好的架构应该能够轻松扩展以满足这些需求,而不需要完全重新设......
  • KdMapper扩展实现之REALiX(hwinfo64a.sys)
    1.背景  KdMapper是一个利用intel的驱动漏洞可以无痕的加载未经签名的驱动,本文是利用其它漏洞(参考《【转载】利用签名驱动漏洞加载未签名驱动》)做相应的修改以实现类似功能。需要大家对KdMapper的代码有一定了解。 2.驱动信息 驱动名称hwinfo64a.sys 时间戳5472......
  • 《复盘:对过去的事情做思维演练》读书笔记
    复盘是对过去所作的事情进行回顾、反思和探究,找出原因,找到规律,从而指导我们解决问题,帮助我们提升。对于复盘来说,回顾、反思、探究、提升,一个都不能少。复盘的由来复盘,原本是围棋中的一个术语。当下完一盘棋之后,要重新再棋盘上走一遍,看看哪些子下的好,哪些子下得不好,哪些地方可以......