FreeRTOS列表系统深度解析

一、核心数据结构

1. 列表控制块 (List_t)
typedef struct xLIST {volatile UBaseType_t uxNumberOfItems;  // 当前列表项数量ListItem_t * pxIndex;                 // 遍历指针(用于轮询调度)MiniListItem_t xListEnd;              // 列表尾标记(哨兵节点)
} List_t;

结构要点

  • xListEnd作为永久存在的尾节点
  • pxIndex指向当前遍历位置
  • uxNumberOfItems提供O(1)的计数查询
2. 列表项 (ListItem_t)
struct xLIST_ITEM {TickType_t xItemValue;                // 排序键值(如唤醒时间)struct xLIST_ITEM * pxNext;           // 后向指针struct xLIST_ITEM * pxPrevious;       // 前向指针void * pvOwner;                       // 所有者(通常为TCB指针)struct xLIST * pxContainer;           // 所属列表指针
};

内存布局

+------------+-----------+-----------+-----------+-----------+
| xItemValue |  pxNext   | pxPrevious| pvOwner   | pxContainer|
| (4 bytes)  | (4 bytes) | (4 bytes) | (4 bytes) | (4 bytes)  |
+------------+-----------+-----------+-----------+-----------+
3. 迷你列表项 (MiniListItem_t)
typedef struct xMINI_LIST_ITEM {TickType_t xItemValue;struct xLIST_ITEM * pxNext;struct xLIST_ITEM * pxPrevious;
} MiniListItem_t;

作用:作为列表头尾节点,减少内存占用


二、列表操作原理

1. 列表初始化
void vListInitialise( List_t * const pxList ) {pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd );pxList->xListEnd.xItemValue = portMAX_DELAY;pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd );pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );pxList->uxNumberOfItems = 0;
}

初始化后状态

      +-------------------+| pxIndex           |----++-------------------+   || xListEnd          |<--+|   xItemValue=MAX  ||   pxNext = ---+   ||   pxPrevious= |   |+---------------|---+^           |+-----------+
2. 有序插入算法
void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem )
{ListItem_t *pxIterator;const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;// 从尾节点开始向前遍历for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd );pxIterator->pxNext->xItemValue <= xValueOfInsertion;pxIterator = pxIterator->pxNext ) { /* 空循环 */ }// 插入新节点pxNewListItem->pxNext = pxIterator->pxNext;pxNewListItem->pxNext->pxPrevious = pxNewListItem;pxNewListItem->pxPrevious = pxIterator;pxIterator->pxNext = pxNewListItem;// 更新元数据pxNewListItem->pxContainer = pxList;( pxList->uxNumberOfItems )++;
}

时间复杂度:O(n) 最坏情况(需遍历整个列表)

3. 列表项移除
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
{List_t * const pxList = pxItemToRemove->pxContainer;// 解除链表关联pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;// 调整遍历指针if( pxList->pxIndex == pxItemToRemove ) {pxList->pxIndex = pxItemToRemove->pxPrevious;}// 清除关联关系pxItemToRemove->pxContainer = NULL;pxList->uxNumberOfItems--;return pxList->uxNumberOfItems;
}

关键点

  • O(1)时间复杂度
  • 自动更新遍历指针
  • 清除容器指针防止误用

三、系统级应用

1. 就绪列表管理
// 全局就绪列表数组(每个优先级一个列表)
PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ];// 添加任务到就绪列表
void prvAddTaskToReadyList( TCB_t *pxTCB )
{// 获取任务优先级UBaseType_t uxPriority = pxTCB->uxPriority;// 添加到对应优先级的列表尾部vListInsertEnd( &( pxReadyTasksLists[ uxPriority ] ),&( pxTCB->xStateListItem ) );// 更新优先级位图portRECORD_READY_PRIORITY( uxPriority );
}
2. 延时列表管理
// 延时列表(按唤醒时间排序)
PRIVILEGED_DATA static List_t xDelayedTaskList1;// 系统时钟中断处理
void xTaskIncrementTick( void )
{TickType_t xItemValue;ListItem_t *pxListItem;// 遍历延时列表pxListItem = listGET_HEAD_ENTRY( &xDelayedTaskList1 );while( listGET_END_MARKER != pxListItem ) {xItemValue = listGET_LIST_ITEM_VALUE( pxListItem );if( xItemValue <= xTickCount ) {// 从延时列表移除uxListRemove( pxListItem );// 添加到就绪列表prvAddTaskToReadyList( ( TCB_t * ) listGET_LIST_ITEM_OWNER( pxListItem ) );} else {break; // 后续任务尚未到期}pxListItem = listGET_NEXT( pxListItem );}
}

四、高级优化技术

1. 优先级位图算法
// 就绪优先级位图(32位系统)
#define portMAX_READY_PRIORITIES ( 32 )
static volatile UBaseType_t uxTopReadyPriority;
static volatile uint32_t uxReadyPriorities[ portMAX_READY_PRIORITIES / 32 ];// 更新位图
void vPortUpdateReadyPriorities( UBaseType_t uxPriority ) {const UBaseType_t uxWord = uxPriority >> 5;  // 除以32const uint32_t ulBit = 1UL << ( uxPriority & 0x1F );// 设置对应位uxReadyPriorities[ uxWord ] |= ulBit;// 更新最高优先级if( uxPriority > uxTopReadyPriority ) {uxTopReadyPriority = uxPriority;}
}// 查找最高就绪优先级
UBaseType_t uxPortGetHighestReadyPriority( void ) {uint32_t ulBits;UBaseType_t uxPriority;// 检查当前最高优先级组ulBits = uxReadyPriorities[ uxTopReadyPriority >> 5 ];if( ulBits != 0 ) {// 使用CLZ指令快速定位uxPriority = ( UBaseType_t ) __clz( __rbit( ulBits ) );uxPriority += ( uxTopReadyPriority & ~0x1F );} else {// 搜索其他优先级组/* ... */}return uxPriority;
}
2. 多级延时列表
// 双缓冲延时列表(防止节拍计数器溢出问题)
static List_t xDelayedTaskList1;
static List_t xDelayedTaskList2;
static List_t * volatile pxDelayedTaskList;
static List_t * volatile pxOverflowDelayedTaskList;// 节拍计数器溢出处理
void vTaskSwitchDelayedLists( void ) {List_t * pxTemp;// 交换当前和溢出列表指针pxTemp = pxDelayedTaskList;pxDelayedTaskList = pxOverflowDelayedTaskList;pxOverflowDelayedTaskList = pxTemp;// 清空新溢出列表vListInitialise( pxOverflowDelayedTaskList );// 提升所有等待计数器xNumOfOverflows++;prvResetNextTaskUnblockTime();
}

五、关键注意事项

1. 临界区保护
// 错误示例(无保护)
vListInsert( &xList, &xItem );// 正确做法
taskENTER_CRITICAL();
{vListInsert( &xList, &xItem );
}
taskEXIT_CRITICAL();
2. 列表项状态管理
// 任务删除前检查
if( pxTask->xStateListItem.pxContainer != NULL ) {uxListRemove( &( pxTask->xStateListItem ) );
}
vTaskDelete( pxTask );
3. 遍历安全
// 安全遍历模式
ListItem_t *pxIterator, *pxNext;
for( pxIterator = listGET_HEAD_ENTRY( pxList );pxIterator != listGET_END_MARKER( pxList );pxIterator = pxNext ) {pxNext = listGET_NEXT( pxIterator );// 处理当前项ProcessItem( listGET_LIST_ITEM_OWNER( pxIterator ) );
}

六、调试与验证

1. 列表完整性检查
BaseType_t xListValidate( List_t *pxList ) {// 检查首尾连接if( pxList->xListEnd.pxNext->pxPrevious != &(pxList->xListEnd) )return pdFAIL;if( pxList->xListEnd.pxPrevious->pxNext != &(pxList->xListEnd) )return pdFAIL;// 检查项计数UBaseType_t uxCount = 0;ListItem_t *pxItem = pxList->xListEnd.pxNext;while( pxItem != &(pxList->xListEnd) ) {uxCount++;pxItem = pxItem->pxNext;}return ( uxCount == pxList->uxNumberOfItems ) ? pdPASS : pdFAIL;
}
2. 性能监测点
// 关键操作耗时统计
#define LIST_OPERATION_START() uint32_t ulStartCycle = DWT->CYCCNT
#define LIST_OPERATION_END(op) \do { \uint32_t ulCycles = DWT->CYCCNT - ulStartCycle; \if( ulCycles > MAX_##op##_CYCLES ) \vLogHighLatency(op, ulCycles); \} while(0)// 使用示例
LIST_OPERATION_START();
vListInsert( &xList, &xItem );
LIST_OPERATION_END(LIST_INSERT);

完整实现参考:FreeRTOS内核源码

  • list.c:列表核心操作实现
  • tasks.c:任务调度与列表集成
  • portable/[Arch]/port.c:架构特定的优先级位图实现

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/917753.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/917753.shtml
英文地址,请注明出处:http://en.pswp.cn/news/917753.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《Linux编译器:gcc/g++食用指南》

坚持用 清晰易懂的图解 代码语言&#xff0c;让每个知识点变得简单&#xff01; &#x1f680;呆头个人主页详情 &#x1f331; 呆头个人Gitee代码仓库 &#x1f4cc; 呆头详细专栏系列 座右铭&#xff1a; “不患无位&#xff0c;患所以立。” 《Linux编译器&#xff1a;GCC…

SparkKV转换算子实战解析

目录 KV算子 parallelizePairs mapToPair mapValues groupByKey reduceByKey sortByKey 算子应用理解 reduceByKey和groupByKey的区别 groupByKeymapValues实现KV数据的V的操作 改进用reduceByKey groupby通过K和通过V分组的模板代码 问题集锦 宝贵的经验 这里会…

深度解析 TCP 三次握手与四次挥手:从原理到 HTTP/HTTPS 的应用

TCP 的三次握手和四次挥手是网络通信的基石&#xff0c;无论是 HTTP 还是 HTTPS&#xff0c;它们都依赖 TCP 提供可靠的传输层服务。本文将用万字篇幅&#xff0c;结合 Mermaid 图表和代码示例&#xff0c;深入讲解 TCP 三次握手、四次挥手的原理、过程、状态变化&#xff0c;以…

Hyper-V + Centos stream 9 搭建K8s集群(一)

一、创建虚拟机一台32G内存&#xff0c;16核心的Win11&#xff0c;已经安装了Hyper-V 管理器。然后也下载了CentOS-Stream-9-latest-x86_64-dvd1.iso的镜像文件。这里Hyper-V创建虚拟机的过程就不赘述了&#xff0c;如果出现虚拟机加载不到镜像的问题&#xff0c;先把这个使用安…

Pygame如何制作小游戏

以下是 Pygame 的详细使用指南&#xff0c;从安装到开发完整游戏的步骤说明&#xff0c;包含代码示例和最佳实践&#xff1a; 一、安装与环境配置 1. 安装 Pygame pip install pygame2. 验证安装 import pygame pygame.init() print(pygame.version.ver) # 应输出版本号&am…

@【JCIDS】【需求论证】联合能力集成与开发系统知识图谱

JCIDS(联合能力集成与开发系统)知识图谱 1. JCIDS概述 2. JCIDS的提出背景 3. JCIDS核心流程 4. JCIDS分析方法 5. JCIDS优势 6. JCIDS与采办系统的关系 7. JCIDS知识图谱结构 8. 对我的启示 9.JCIDS(联合能力集成与开发系统)相关术语列表 10. 参考文献 1. JCIDS概述 定义:…

每天学一个Linux命令(38):vi/vim

每天学一个 Linux 命令(38):vi/vim vi 和 vim(Vi IMproved)是 Linux 和 Unix 系统中功能强大的文本编辑器。vim 是 vi 的增强版,提供语法高亮、多级撤销、插件支持等更多功能。掌握 vi/vim 是 Linux 系统管理员的必备技能之一。 1. 命令简介 vi:经典的文本编辑器,几乎…

【PZ-ZU49DR-KFB】:璞致电子 UltraScale+ RFSoC 架构下的软件无线电旗舰开发平台

璞致电子 PZ-ZU49DR-KFB 开发板基于 Xilinx ZYNQ UltraScale RFSoC XCZU49DR 主控制器&#xff0c;以 "ARMFPGA 异构架构" 为核心&#xff0c;融合高带宽信号采集、高速数据处理与灵活扩展能力&#xff0c;专为专业工程师打造的软件无线电&#xff08;SDR&#xff09…

力扣106:从中序与后序遍历序列构造二叉树

力扣106:从中序与后序遍历序列构造二叉树题目思路代码题目 给定两个整数数组 inorder 和 postorder &#xff0c;其中 inorder 是二叉树的中序遍历&#xff0c; postorder 是同一棵树的后序遍历&#xff0c;请你构造并返回这颗 二叉树 。 思路 我们首先要知道中序遍历和后序…

IDEA JAVA工程入门

Maven配置&#xff1a; IDEA -> settings -> Build, Execution, Deployment -> Build Tools -> MavenMaven home pathUser setting file : 特定仓库下载依赖包&#xff0c;自动下载(界面右边M图标点开&#xff0c;)local repository &#xff08;本地仓库&#xff…

Spring依赖注入:从原理到实践的自学指南

Spring依赖注入&#xff1a;从原理到实践的自学指南 一、什么是依赖注入&#xff1f; 依赖注入&#xff08;Dependency Injection, DI&#xff09;是Spring框架实现控制反转&#xff08;IoC&#xff09;的核心手段。其核心思想是&#xff1a;对象不再自己创建依赖项&#xff…

3_软件重构_组件化开发实例方法论

1、上期回顾上次内容核心的地方有两个&#xff0c;①是C多态基类的指针指向派生类&#xff0c;用于初始化各个插件。②是使用C语言的dlopen函数“动态加载”各个插件&#xff0c;实现用户根据契约接口自定义开发插件&#xff0c;极大程度地实现了软件上的解耦。③再进一步&…

C#接口的定义与使用

第1章 接口&#xff08;interface&#xff09;是什么1.1 定义• 接口是一组“能力”或“契约”的抽象描述&#xff0c;只规定“能做什么”&#xff0c;不规定“怎么做”。• 在 C# 中&#xff0c;接口是一种完全抽象的类型&#xff08;fully abstract type&#xff09;。 • 关…

【STM32】HAL库中的实现(三):PWM(脉冲宽度调制)

&#x1f527; HAL库中的实现&#xff1a;PWM&#xff08;脉冲宽度调制&#xff09; PWM&#xff08;Pulse Width Modulation&#xff09;是基于定时器&#xff08;TIM&#xff09;产生的周期性脉冲信号&#xff0c;广泛应用于&#xff1a;① 电机调速&#xff1b;② LED 亮度控…

GitHub 趋势日报 (2025年08月03日)

&#x1f680; GitHub 趋势日报 (2025年08月03日) &#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图751dyad362LLMs-from-scratch291…

Java后端高频面试题

Java后端高频面试题 目录 Java集合框架Java并发编程JVM相关MySQL数据库Redis缓存Spring框架 Java集合框架 HashMap的数据结构是什么&#xff0c;为什么在JDK8要引入红黑树&#xff1f; HashMap数据结构&#xff1a; JDK7&#xff1a;数组 链表JDK8&#xff1a;数组 链表…

37. line-height: 1.2 与 line-height: 120% 的区别

概述 line-height 是 CSS 中用于控制文本行间距的重要属性。虽然 line-height: 1.2 和 line-height: 120% 看似相同&#xff0c;但它们在计算方式上存在关键区别&#xff0c;尤其是在继承和计算值方面。1. 计算方式不同写法类型计算方式说明line-height: 1.2无单位&#xff08;…

蓝桥杯----DS1302实时时钟

&#xff08;六&#xff09;、DS1302实时时钟1、原理&#xff08;图 二十六&#xff09;DS1302通过三线串行接口与单片机进行通信。微控制器可以通过设置RST引脚为高电平来使能DS1302&#xff0c;并通过SCK引脚提供串行时钟信号&#xff0c;然后通过I/O引脚进行数据的读写操作。…

C++对象访问有访问权限是不是在ide里有效

在C中&#xff0c;对象的访问权限&#xff08;即公有&#xff08;public&#xff09;、保护&#xff08;protected&#xff09;和私有&#xff08;private&#xff09;成员的访问&#xff09;是编译时的一部分&#xff0c;而不是运行时。这意味着&#xff0c;无论是在IDE&#…

CubeMX安装芯片包

1.点击HELP2.选择公理嵌入式软件包3.选择并下载芯片包