FreeRTOS數據結構(一)--鏈表和鏈表項
阿新 • • 發佈:2018-04-28
set 開關 部分 添加 use XP prev inf ext (mini鏈表項沒有定義這個),該定義是一個16位或32位的整形數,在鏈表或鏈表項初始化的時候會將該變量初始化為0x5a5a或0x5a5a5a5a,在檢查的時候如果這兩個變量都沒有改變則通過完整性檢查,否則認為鏈表被破壞。
結構體定義
/*鏈表結構體*/ typedef struct xLIST { listFIRST_LIST_INTEGRITY_CHECK_VALUE /*用於鏈表完整性檢查*/ configLIST_VOLATILE UBaseType_t uxNumberOfItems; /*記錄鏈表項數目*/ ListItem_t * configLIST_VOLATILE pxIndex; /*用於遍歷鏈表,初始化會指向最後的鏈表項,這裏需要註意使用了volatile關鍵字,表明該指針可能會在其他地方修改*/ MiniListItem_t xListEnd;/*用於標記鏈表尾*/ listSECOND_LIST_INTEGRITY_CHECK_VALUE /*用於鏈表完整性檢查*/ } List_t; /*鏈表項結構體*/ 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; /*指向結構體控制塊*/ void * configLIST_VOLATILE pvContainer;/*指向該鏈表項對應的鏈表*/ listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE /*用於鏈表完整性檢查*/ }; /*迷你鏈表項結構體*/ 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; };
根據定義可以看出以下幾點:
- 鏈表結構是一個雙向鏈表。
- 每個鏈表都由鏈表和鏈表項組成。
- 鏈表結構體本身有一個迷你鏈表項,用來標記鏈表的結尾。
鏈表和鏈表項初始化
/*鏈表初始化*/ void vListInitialise( List_t * const pxList ) { /*將鏈表的Index索引指針指向自身的迷你鏈表項,即鏈表結尾*/ 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 = ( UBaseType_t ) 0U; /*初始化鏈表的完整性檢查值*/ listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ); listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ); } /*鏈表項初始化*/ 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 ); }
鏈表的操作
鏈表的插入會根據List Item Value進行升序排列,其他並沒有什麽特殊的地方。初始化並插入兩個節點後大概的數據結構,如下圖所示:
從圖中可以看出,List初始化並添加節點後,List Item 1/List Item 2 和 List自己的xListEnd節點一起組成了一個雙向循環的鏈表。
Q&A
1).如何完成鏈表的完整性檢查?
如果打開了完整性檢查的開關(configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES),每個鏈表和鏈表項結構都會定義listFIRST_LIST_INTEGRITY_CHECK_VALUE和listSECOND_LIST_INTEGRITY_CHECK_VALUE
2).如何使用List?
- 必須先定義一個List_t的全局變量,比如Timer中的 xActiveTimerList1
- 每一個節點結構體必須包含xLIST_ITEM類型的成員。
- 初始化鏈表後,將含有List Item成員的數據結構按照鏈表項值的大小插入到鏈表中,比如Timer中利用該值溢出的判斷。
- 設置好pvOwner指針,後續可以根據該指針反向找到該節點的具體結構,如Timer_t。
FreeRTOS數據結構(一)--鏈表和鏈表項