FreeRTOS列表和列表項

FreeRTOS內核調度使用了大量的列表(list)和列表項(listitem)數據結構。它的源碼中涉及到很多列表的操作,對于FreeRTOS來說,列表就是它最基礎的一部分,列表被用作FreeRTOS調度器使用,用于跟蹤任務,處于就緒,掛起,延時的任務都會被掛接到各自的列表中,用戶程序如果有需要,也可以使用列表,其中就連FreeRTOS的任務調度其實核心也涉及到列表。

? FreeRTOS列表使用指針指向列表項。一個列表(list)下面可能有很多個列表項(list item),每個列表項都有一個指針指向列表。如圖所示

列表和列表項

列表項有兩種形式,全功能版的列表項xLIST_ITEM和迷你版的列表項xMINI_LIST_ITEM。我們來看一下它們具體的定義,先看全功能版。

struct xLIST_ITEM
{listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE           /*用于檢測列表項數據是否完整*/configLIST_VOLATILE TickType_t xItemValue;           /*列表項值*/struct xLIST_ITEM * configLIST_VOLATILE pxNext;      /*指向列表中下一個列表項*/struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;  /*指向列表中上一個列表項*/void * pvOwner;                                     /*指向一個任務TCB*/void * configLIST_VOLATILE pvContainer;             /*指向包含該列表項的列表 */listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE          /*用于檢測列表項數據是否完整*/
};
typedef struct xLIST_ITEM ListItem_t;

? ?宏listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE和listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE用于檢查列表項數據是否完整,在projdefs.h中,如果將宏configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES設置為1,則使能列表項數據完整性檢查,則宏listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE和listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE會被兩個已知的數值代替。

? ? ? xItemValue是列表項值,通常是一個被跟蹤的任務優先級或是一個調度事件的計數器值。如果任務因為等待從隊列取數據而進入阻塞狀態,則任務的事件列表項的列表項值保存任務優先級有關信息,狀態列表項的列表項值保存阻塞時間有關的信息。這個變量被configLIST_VOLATILE修飾,configLIST_VOLATILE被映射成C語言關鍵字volatile,表明這個變量是“易變的”,告訴編譯器不得對這個變量進行代碼優化,因為列表項的成員可能會在中斷服務程序中被更新。

? pxNext和pxPrevious是列表項類型指針,用來指向列表中下一個和上一個列表項,通過這兩個指針,列表項之間可以形成類似雙向鏈表結構。

? ? ? 指針pvOwner通常指向一個任務TCB。

? ? ? 指針pvContainer指向包含該列表項的列表。

? ? ? 迷你版的列表項xMINI_LIST_ITEM是全功能版列表項xLIST_ITEM的一個子集,定義如下所示:
?

struct xMINI_LIST_ITEM
{listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE           /*用于檢測列表項數據是否完整*/configLIST_VOLATILE TickType_t xItemValue;struct xLIST_ITEM * configLIST_VOLATILE pxNext;struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;
};
typedef struct xMINI_LIST_ITEM MiniListItem_t;

??? 既然有了全功能版的列表項,為什么還要聲明迷你版的列表項呢?這是因為列表結構體需要一個列表項成員,但又不需要列表項中的所有字段,所以才有了迷你版列表項。迷你列表項起到的主要作用就是標識列表的末尾,所以它的值也設置成了最大值,列表結構體定義為:

typedef struct xLIST
{listFIRST_LIST_INTEGRITY_CHECK_VALUE                        /*用于檢測列表項數據是否完整*/configLIST_VOLATILE UBaseType_t uxNumberOfItems;ListItem_t * configLIST_VOLATILE pxIndex;                   /*用于遍歷列表*/MiniListItem_t xListEnd;                                    /*列表項*/listSECOND_LIST_INTEGRITY_CHECK_VALUE                       /*用于檢測列表項數據是否完整*/
}List_t;

?

和列表項定義相同,宏listFIRST_LIST_INTEGRITY_CHECK_VALUE和listSECOND_LIST_INTEGRITY_CHECK_VALUE用于檢查列表項數據是否完整,在projdefs.h中,如果將宏configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES設置為1,則使能列表項數據完整性檢查,則宏listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE和listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE會被兩個已知的數值代替。

? ? ? uxNumberOfItems表示該列表中掛接的列表項數目,0表示列表為空。

? ? ? 列表項類型指針用于遍歷列表,列表初始化后,這個指針指向&xListEnd。通過宏listGET_OWNER_OF_NEXT_ENTRY()來獲取列表中的下一個列表項。

? ? ? 列表項xListEnd用于標記列表結束。xListEnd.xItemValue被初始化為一個常數,其值與硬件架構相關,為0xFFFF(16位架構)或者0xFFFFFFFF(32位架構)。
?

關于列表的一些操作

初始化列表

列表結構體中包含一個列表項成員,主要用于標記列表結束。初始化列表就是把這個列表項插入到列表中。

void vListInitialise( List_t * const pxList )
{/*列表索引指向列表項*/pxList->pxIndex = ( ListItem_t * )&( pxList->xListEnd );                  /* 設置為最大可能值 */pxList->xListEnd.xItemValue =portMAX_DELAY;/* 列表項xListEnd的pxNext和pxPrevious指針指向了它自己 */pxList->xListEnd.pxNext = (ListItem_t * ) &( pxList->xListEnd );pxList->xListEnd.pxPrevious= ( ListItem_t * ) &( pxList->xListEnd );pxList->uxNumberOfItems = ( UBaseType_t) 0U;/* 設置為已知值,用于檢測列表數據是否完整*/listSET_LIST_INTEGRITY_CHECK_1_VALUE(pxList );listSET_LIST_INTEGRITY_CHECK_2_VALUE(pxList );
}

如果宏configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES設置為1,則使能列表項數據完整性檢查,則宏listSET_LIST_INTEGRITY_CHECK_1_VALUE()和listSET_LIST_INTEGRITY_CHECK_2_VALUE被一個已知值代替,默認為0x5a5a(16位架構)或者0x5a5a5a5a(32位架構)。

? ? ? 假設禁止列表數據完整性檢查,初始化后的列表如圖1-2所示,uxNumberOfItems被初始化為0,xListEnd.xItemValue初始化為0xffffffff,pxIndex、xListEnd.pxNext和xListEnd.pxPrevious初始化為指向列表項xListEnd。
?

?初始化列表項

列表項的初始化很簡答, 只需要聲明該列表項不屬于任何一個列表就可以了。

void vListInitialiseItem( ListItem_t * const pxItem )
{pxItem->pvContainer = NULL;/*設置為已知值,用于檢測列表項數據是否完整*/listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE(pxItem );listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE(pxItem );
}

如果宏configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES設置為1,則使能列表項數據完整性檢查,則宏listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE和listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE會被兩個已知的數值代替,默認為0x5a5a(16位架構)或者0x5a5a5a5a(32位架構)。

? ? ? 假設禁止列表項數據完整性檢查,初始化后的列表項如圖1-3所示。僅是將指針pvContainer設置為空指針,該指針用于指向包含該列表項的列表,這里設置為NULL表示這個列表項不屬于任何列表。
?

?

列表插入列表項

?

每個列表項對象都有一個列表項值(xItemValue),通常是一個被跟蹤的任務優先級或是一個調度事件的計數器值。調用API函數vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem)可以將pxNewListItem指向的列表項插入到pxList指向的列表中,列表項在列表的位置由pxNewListItem->xItemValue決定,按照升序排列。

void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem )
{
ListItem_t *pxIterator;
const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;/* 檢查列表和列表項數據的完整性,僅當configASSERT()定義時有效。*/listTEST_LIST_INTEGRITY( pxList );listTEST_LIST_ITEM_INTEGRITY(pxNewListItem );/*將新的列表項插入到列表,根據xItemValue的值升序插入列表。*/if( xValueOfInsertion == portMAX_DELAY){pxIterator =pxList->xListEnd.pxPrevious;}else{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->pvContainer = ( void* ) pxList;( pxList->uxNumberOfItems )++;
}

?列表項末尾插入

void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem )
{
ListItem_t* const pxIndex = pxList->pxIndex;/*檢查列表和列表項數據的完整性,僅當configASSERT()定義時有效。*/listTEST_LIST_INTEGRITY( pxList );listTEST_LIST_ITEM_INTEGRITY(pxNewListItem );/*向列表中插入新的列表項*/pxNewListItem->pxNext = pxIndex;pxNewListItem->pxPrevious =pxIndex->pxPrevious;mtCOVERAGE_TEST_DELAY();pxIndex->pxPrevious->pxNext =pxNewListItem;pxIndex->pxPrevious = pxNewListItem;pxNewListItem->pvContainer = ( void* ) pxList;( pxList->uxNumberOfItems )++;
}

Tips: 這個函數是最容易造成誤解的一個函數,字面理解,在我開始學的時候我以為就是插入到最后一個迷你列表項的前面,所謂末尾插入肯定是最后一項嘛,閱讀源碼之后,其實不然,因為列表中有一項成員?

ListItem_t * configLIST_VOLATILE pxIndex; 

該成員主要作用就是用來遍歷列表的。閱讀源碼發現它是插入在pxIndex所指的列表項的前面。這里體現了FreeRTOS的哲學理念,“公平”,如果pxIndex,指向的是當前的索引的列表項表示正在使用,這時比如順序是1->2->3,現在pxIndex指向2,要插入4,這時你4肯定是要最后遍歷訪問的,意味著就是訪問順序應該是2->3->1->4,所以它要插入在2前面,我的方法是記住一個口訣,末尾插入就是插入pxIndex所指列表項的前一項的后面,可能聽著有點別扭(不就是所指列表項的前面嘛🤣 ,細細體會,有公平的哲學思想)

重點

重點:一開始學習的時候,一直不明白這個pxIndex有什么用,因為我在有關列表的list.c中的API函數中根本沒發現有改變它的代碼,以為它一直是初始化的值,就是一直指向迷你列表項,其實不然,作為一名程序員,一切從源碼中得到答案。

搜索代碼之后發現,中間對pxIndex賦值的地方只有listGET_OWNER_OF_NEXT_ENTRY這個接口(list.h中的一個有參宏)

?每調用一次listGET_OWNER_OF_NEXT_ENTRY,列表的pxIndex會指向下一個列表項。
而調用listGET_OWNER_OF_NEXT_ENTRY,主要是

?

FreeRTOS的列表和列表項采用了一種統一的列表管理,不像我以前學的數據結構中的鏈表操作一樣,其中的節點都是具體的結構體的內容,所以是針對具體的一類結構體,比如struct people,這樣導致的后果就是所有有關鏈表操作的內容都是針對這類結構體,如果稍微改成struct dog,這樣就需要全部重寫鏈表的所有操作了。FreeRTOS采用一種方法,寫出了通用的鏈表操作,讓我不得不感嘆這代碼確實是寫的好!🤣?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:
http://www.pswp.cn/news/160623.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/160623.shtml
英文地址,請注明出處:http://en.pswp.cn/news/160623.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

力扣.面試題 04.06. 后繼者(java 樹的中序遍歷)

Problem: 面試題 04.06. 后繼者 文章目錄 題目描述思路解題方法復雜度Code 題目描述 設計一個算法&#xff0c;找出二叉搜索樹中指定節點的“下一個”節點&#xff08;也即中序后繼&#xff09;。 如果指定節點沒有對應的“下一個”節點&#xff0c;則返回null。 思路 由于題…

lombok @Slf4j注解啥作用

Logger logger Logger.getLogger(Test.class); logger.debug("這是一個調試信息"); logger.info("這是一個info信息");log4j 使用分兩步 第一步&#xff1a;private final Logger logger LoggerFactory.getLogger(當前類名.class); 第二步&#xff1a;記…

Python開發運維:Celery連接Redis

目錄 一、理論 1.Celery 二、實驗 1.Windows11安裝Redis 2.Python3.8環境中配置Celery 三、問題 1.Celery命令報錯 2.執行Celery命令報錯 3.Win11啟動Celery報ValueErro錯誤 一、理論 1.Celery (1) 概念 Celery是一個基于python開發的分布式系統&#xff0c;它是簡單…

Linux 命令: cut 和 tr

1. 寫在前面 本文主要介紹&#xff1a;Linux "cut "和 “tr” 命令行實用程序概述&#xff1b; 公眾號&#xff1a; 滑翔的紙飛機 2. Linux 命令&#xff1a; cut “cut” 命令是一種命令行工具&#xff0c;允許我們剪切指定文件或管道數據的部分內容&#xff0c;并…

JSP內置對象

一、request對象 1、訪問請求參數 2、在作用域中管理屬性 3、獲取Cookie 4、解決中文亂碼 5、獲取客戶端信息 6、顯示國際化信息 是一個javax.servlet.http.HttpServletRequest對象 request封裝了用戶瀏覽器提交的信息&#xff0c;因此可以調用相應的方法可以獲取這些封…

優先經驗回放(prioritized experience replay)

prioritized experience replay 思路 優先經驗回放出自ICLR 2016的論文《prioritized experience replay》。 prioritized experience replay的作者們認為&#xff0c;按照一定的優先級來對經驗回放池中的樣本采樣&#xff0c;相比于隨機均勻的從經驗回放池中采樣的效率更高&…

UML建模圖文詳解教程——類圖

版權聲明 本文原創作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl本文參考資料&#xff1a;《UML面向對象分析、建模與設計&#xff08;第2版&#xff09;》呂云翔&#xff0c;趙天宇 著 類圖概述 類圖用來描述系統內各種實體的類型以及不同…

Unsupervised MVS論文筆記

Unsupervised MVS論文筆記 摘要1 引言2 相關工作3 實現方法 Tejas Khot and Shubham Agrawal and Shubham Tulsiani and Christoph Mertz and Simon Lucey and Martial Hebert. Tejas Khot and Shubham Agrawal and Shubham Tulsiani and Christoph Mertz and Simon Lucey and …

JAVA小游戲拼圖

第一步是創建項目 項目名自擬 第二部創建個包名 來規范class 然后是創建類 創建一個代碼類 和一個運行類 代碼如下&#xff1a; package heima; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import …

10、信息打點——APP小程序篇抓包封包XP框架反編譯資產提取

APP信息搜集思路 外在——抓包封包——資產安全測試 抓包&#xff08;Fiddle&茶杯&burp&#xff09;封包&#xff08;封包監聽工具&#xff09;&#xff0c;提取資源信息 資產收集——資源提取——ICO、MAD、hash——FOFA等網絡測繪進行資產搜集 外在——功能邏輯 內在…

國際版Amazon Lightsail的功能解析

Amazon Lightsail是一項易于使用的云服務,可為您提供部署應用程序或網站所需的一切,從而實現經濟高效且易于理解的月度計劃。它是部署簡單的工作負載、網站或開始使用亞馬遜云科技的理想選擇。 作為 AWS 免費套餐的一部分&#xff0c;可以免費開始使用 Amazon Lightsail。注冊…

【Python進階】近200頁md文檔14大體系第4篇:Python進程使用詳解(圖文演示)

本文從14大模塊展示了python高級用的應用。分別有Linux命令&#xff0c;多任務編程、網絡編程、Http協議和靜態Web編程、htmlcss、JavaScript、jQuery、MySql數據庫的各種用法、python的閉包和裝飾器、mini-web框架、正則表達式等相關文章的詳細講述。 Python全套筆記直接地址…

PostgreSQL10安裝postgis插件

1.安裝pgsql10 2.下載插件&#xff0c;以Windows為例&#xff0c;地址&#xff1a;Index of /postgis/windows/pg10/ 3.安裝插件&#xff0c;直接安裝&#xff0c;和pgsql的目錄相同即可&#xff0c;一直下一步 4.安裝之后&#xff0c;需要執行sql打開 CREATE EXTENSION po…

028 - STM32學習筆記 - ADC結構體學習(二)

028 - STM32學習筆記 - 結構體學習&#xff08;二&#xff09; 上節對ADC基礎知識進行了學習&#xff0c;這節在了解一下ADC相關的結構體。 一、ADC初始化結構體 在標準庫函數中基本上對于外設都有一個初始化結構體xx_InitTypeDef&#xff08;其中xx為外設名&#xff0c;例如…

Redis設計與實現-數據結構(建設進度17%)

Redis數據結構 引言數據結構stringSDS數據結構原生string的不足 hash 本博客基于《Redis設計與實現》進行整理和補充&#xff0c;該書依賴于Redis 3.0版本&#xff0c;但是Redis6.0版本在一些底層實現上仍然沒有明顯的變動&#xff0c;因此本文將在該書的基礎上&#xff0c;對于…

PostgreSQL基本操作

1.查詢某個表的所在磁盤大小 select pg_size_pretty(pg_relation_size(grb_grid)); 2.插入point類型的記錄 insert into tb_person ("name", "address", "location", "create_time", "area", "girls") values …

Java 兩個線程交替打印1-100

線程題&#xff1a;交替打印1-100 這里演示兩個線程&#xff0c;一個打印奇數&#xff0c;一個打印偶數 方式一&#xff1a;synchronized FixedThreadPool public class example {private static int count 1;private static final Object lock new Object();public stat…

WPF基礎DataGrid控件

WPF DataGrid 是一個用于顯示和編輯表格數據的強大控件。它提供了豐富的功能&#xff0c;包括排序、篩選、分組、編輯、選擇等&#xff0c;使你能夠以類似電子表格的方式呈現和操作數據。 DataGrid 的布局主要由以下部分組成&#xff1a; 列定義 (Columns): DataGrid 列定義了…

YOLO目標檢測——衛星遙感多類別檢測數據集下載分享【含對應voc、coco和yolo三種格式標簽】

實際項目應用&#xff1a;衛星遙感目標檢測數據集說明&#xff1a;衛星遙感多類別檢測數據集&#xff0c;真實場景的高質量圖片數據&#xff0c;數據場景豐富&#xff0c;含網球場、棒球場、籃球場、田徑場、儲罐、車輛、橋、飛機、船等類別標簽說明&#xff1a;使用lableimg標…

2023年【上海市安全員C證】考試及上海市安全員C證找解析

題庫來源&#xff1a;安全生產模擬考試一點通公眾號小程序 2023年上海市安全員C證考試為正在備考上海市安全員C證操作證的學員準備的理論考試專題&#xff0c;每個月更新的上海市安全員C證找解析祝您順利通過上海市安全員C證考試。 1、【多選題】2017年9月頒發的《中共上海市委…