FreeRTOS列表与列表项

news/2024/12/21 21:50:28/

1.什么是列表与列表项

列表与列表项实际上是FreeRTOS中一个大量使用的一种数据结构

1.列表

列表的概念有点像链表,在 FreeRTOS 中,列表主要用于以下几个方面:

  1. 任务的管理:FreeRTOS 使用列表来管理不同的任务,包括就绪任务列表、阻塞任务列表等。任务列表按任务优先级或其他条件进行排序,以便调度器能够快速选择下一个要执行的任务
  2. 定时器:FreeRTOS 使用列表来管理软件定时器。定时器列表按定时器到期时间排序,这样在系统时钟中断时,可以快速检查是否有定时器到期
  3. 事件管理:FreeRTOS 使用列表来管理事件和资源,如信号量、互斥量等。这些列表有助于跟踪哪些任务在等待某个事件或资源

在list.h种,有如下结构体定义

typedef struct xLIST
{listFIRST_LIST_INTEGRITY_CHECK_VALUE      /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */volatile UBaseType_t uxNumberOfItems;ListItem_t * configLIST_VOLATILE pxIndex; /*< Used to walk through the list.  Points to the last item returned by a call to listGET_OWNER_OF_NEXT_ENTRY (). */MiniListItem_t xListEnd;                  /*< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */listSECOND_LIST_INTEGRITY_CHECK_VALUE     /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
} List_t;
  • listFIRST_LIST_INTEGRITY_CHECK_VALUE:

这个实际上是一个用于列表完整性检查的一个宏,它的主要作用是帮助检测内存损坏或者意外的列表结构修改。它通常被定义为某个常量值,当 FreeRTOS 创建或修改列表时,会使用这个常量值来设置列表结构中的特定字段。然后,在后续的操作中,FreeRTOS 会检查这些字段的值,以确保列表没有被意外修改或损坏

我们后续编程不需要关心这个宏。

  • uxNumberOfItems

列表中列表项的数量

  • pxIndex:

记录当前列表项的索引号,用于遍历列表

  • xListEnd:

列表中最后一个列表项

2.列表项

列表项(List Item)是一个数据结构,用于在列表(List)中存储和管理信息。每个列表项代表一个节点或单元,可以包含指向其他相关数据的指针

FreeRTOS共有两种列表项,分别是列表项和迷你列表项

1.列表项的结构体定义如下:

struct xLIST_ITEM
{listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE           /*不用关心< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */configLIST_VOLATILE TickType_t xItemValue;          /*实际的数据< The value being listed.  In most cases this is used to sort the list in ascending order. */struct xLIST_ITEM * configLIST_VOLATILE pxNext;     /*指向下一个列表项< Pointer to the next ListItem_t in the list. */struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; /*指向前一个列表项< Pointer to the previous ListItem_t in the list. */void * pvOwner;                                     /*指向列表项的创建者< Pointer to the object (normally a TCB) that contains the list item.  There is therefore a two way link between the object containing the list item and the list item itself. */struct xLIST * configLIST_VOLATILE pxContainer;     /*此列表项所属的列表< Pointer to the list in which this list item is placed (if any). */listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE          /*不用关心< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
};
typedef struct xLIST_ITEM ListItem_t;                   /* For some reason lint wants this as two separate definitions. */
  • listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE:

检查列表项完整性

  • xItemValue

列表项值

  • pxNext

指向下一个列表项

  • pxPrevious

指向前一个列表项

  • pvOwner

指向拥有该列表项的对象,列表项用于管理任务时,通常指向该任务的任务控制块(TCB)

  • pxContainer

指向此列表项所属的列表。

注意这个和pvOwner并不冲突,我们在前面讲TCB程序控制块时,TCB有两个列表项,比如说这个状态列表项,当创建一个任务后,这个状态列表项中的pvOwner就指向这个任务的TCB,如果这个任务进入就绪状态后,那么这个状态列表项的pxContainer就指向就绪列表,表明此列表项在就绪列表中。如果程序进入挂起状态后,那么pxContainer就指向挂起列表,表明此列表项在挂起列表中

2.迷你列表项

在某些情况下,我们不需要列表项的所有功能,为了节省资源,我们可以采用迷你列表项,比如我们列表中最后一个列表项的类型就是xMINI_LIST_ITEM类型的迷你列表项,其定义如下:

struct xMINI_LIST_ITEM{listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */configLIST_VOLATILE TickType_t xItemValue;struct xLIST_ITEM * configLIST_VOLATILE pxNext;struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;};
  • listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE

检查列表项完整性

  • xItemValue

列表项值

  • pxNext

指向下一列表项

  • pxPrevious

指向上一列表项

2.列表与列表项相关操作

1.列表与列表项初始化

新建列表需要初始化,通过调用函数vListInitialise()完成,列表项也是如此,通过函数vListInitialiseItem()完成。虽然函数的内部构造很复杂,但我们使用起来是叫较为简单的,所以不需要花费太多时间。

2.列表项插入

1)插入

列表项的插入通过函数vListInsert()完成,其函数原型如下

void vListInsert( List_t * const pxList,ListItem_t * const pxNewListItem )

参数

pxList: 列表项要插入的列表

pxNewListItem 要插入的列表项

需要注意的是,列表项插入是根据列表项值的升序进行排列的


void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem )
{ListItem_t *pxIterator;const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
//列表项中实际的有效数值   listTEST_LIST_INTEGRITY( pxList );listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );if( xValueOfInsertion == portMAX_DELAY )//插入的位置,列表项插入是根据项值的升序进行排列的,也就是升序排列的是列表项的优先级{pxIterator = pxList->xListEnd.pxPrevious;}else{//判断插入的位置for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*lint !e826 !e740 The mini list structure is used as the list end to save RAM.  This is checked and valid. */{}}pxNewListItem->pxNext = pxIterator->pxNext;//列表项的下一节点pxNewListItem->pxNext->pxPrevious = pxNewListItem;//列表项的尾节点指向头结点,类似循环列表pxNewListItem->pxPrevious = pxIterator;//列表项的上一节点pxIterator->pxNext = pxNewListItem;pxNewListItem->pvContainer = ( void * ) pxList;//修改列表项的所属者,属于就绪列表、阻塞列表( pxList->uxNumberOfItems )++;//长度加1
}

2)末尾插入

列表项末尾插入通过函数vListInsertEnd()完成,其原型如下,其入参和vListInsert()一样:


void vListInsertEnd( List_t * const pxList,ListItem_t * const pxNewListItem )

需要注意的是,这个末尾并不是同学们想象的那样,因为我们列表本身是个环形列表,列表中pxIndex是用来遍历列表的,所以它指向的列表项实际上就是表头,所以新的列表项会插入到pxIndex所指向列表项的前面(即最后遍历),而非插到xListEnd的后面。

3)列表项删除

列表项的删除也比较简单,通过uxListRemove()完成,其函数原型如下,传参只有一个,就是要删除的列表项:

UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )

4)遍历

列表中的成员变量pxInedx,FreeRTO提供了函数接口listGET_OWNER_OF_NEXT_ENTRY(),其实现如下:

listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList )   

http://www.ppmy.cn/news/1533861.html

相关文章

【知了社保-注册安全分析报告-无验证方式导致安全隐患】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 1. 暴力破解密码&#xff0c;造成用户信息泄露 2. 短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉 3. 带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造…

django使用笔记6--docker部署

django使用笔记--docker部署 多环境配置创建环境变量配置文件静态资源配置dockerfile配置 由于服务器中python版本和依赖与本地开发环境不同&#xff0c;且centOS7中python及依赖安装更新较为麻烦&#xff0c;所以采用docker容器部署 多环境配置 多环境配置类似Spring中的多环…

鸿蒙应用开发前置学习-TypeScript

注意&#xff1a;博主有个鸿蒙专栏&#xff0c;里面从上到下有关于鸿蒙next的教学文档&#xff0c;大家感兴趣可以学习下 如果大家觉得博主文章写的好的话&#xff0c;可以点下关注&#xff0c;博主会一直更新鸿蒙next相关知识 专栏地址: https://blog.csdn.net/qq_56760790/…

2022浙江省赛G I M

G - Easy Glide 题意 思路 由于数据范围比较小&#xff08;1e3&#xff09;,把所有的移动的时间转化为图论上的边权就可以了,再用dijkstra解决,注意如果用的是邻接表存的话要建双向边 代码 #include <map> #include <set> #include <queue> #include <…

Vue3动态导入后端路由

动态获取文件 // modules就是一个map&#xff0c;文件路径作为key&#xff0c;文件对象作为value const modulesimport.meta.glob(../views/**/*.vue)获取到的modules对象如下&#xff1a; 添加动态路由 import {createRouter, createWebHashHistory} from vue-routerconst m…

16、网络安全合规主体与依据

数据来源&#xff1a;2.网络安全合规主体与依据_哔哩哔哩_bilibili 网络安全合规 界定 网络安全合规是指网络运营者全面遵守网络安全法律&#xff08;如《网络安全法》&#xff09;、国家标准&#xff08;如《个人信息安全规范》&#xff09;及相关规范&#xff0c;以避免法…

浅谈音频采集方案

音频采集的重要性 想象一下&#xff0c;一个清晰、流畅的声音就像是信息传递的桥梁&#xff0c;连接着你我之间的沟通。当你在会议中与同事讨论重要项目时&#xff0c;音频采集确保每一个细节都不会被遗漏&#xff0c;每一句话都像是在耳边轻声细语&#xff0c;非常清晰。 在…

亚信安全发布第34期《勒索家族和勒索事件监控报告》

本周态势快速感知 本周全球共监测到勒索事件91起&#xff0c;近三周勒索事件数量较为稳定。从整体上看&#xff0c;Ransomhub是影响最严重的勒索家族&#xff1b;Play和ElDorado恶意家族也是两个活动频繁的恶意家族&#xff0c;需要注意防范。本周&#xff0c;土耳其公司巴克皮…