結構體定義 根據定義可以看出以下幾點: 1. 鏈表結構是一個雙向鏈表。 2. 每個鏈表都由鏈表和鏈表項組成。 3. 鏈表結構體本身有一個迷你鏈表項,用來標記鏈表的結尾。 鏈表和鏈表項初始化 鏈表的操作 鏈表的插入會根據List Item Value進行升序排列,其他並沒有什麼特殊的地方。初始化並插入 ...
結構體定義
/*鏈表結構體*/
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(mini鏈表項沒有定義這個),該定義是一個16位或32位的整形數,在鏈表或鏈表項初始化的時候會將該變數初始化為0x5a5a或0x5a5a5a5a,在檢查的時候如果這兩個變數都沒有改變則通過完整性檢查,否則認為鏈表被破壞。
2).如何使用List?
- 必須先定義一個List_t的全局變數,比如Timer中的 xActiveTimerList1
- 每一個節點結構體必須包含xLIST_ITEM類型的成員。
- 初始化鏈表後,將含有List Item成員的數據結構按照鏈表項值的大小插入到鏈表中,比如Timer中利用該值溢出的判斷。
- 設置好pvOwner指針,後續可以根據該指針反向找到該節點的具體結構,如Timer_t。