FreeRTOS列表系統深度解析

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.選擇并下載芯片包