一、列表和列表項簡介
????????列表是 FreeRTOS 中的一個數據結構,列表被用來跟蹤 FreeRTOS中的任務(任務當前的狀態),列表項就是存放在列表中的項目
????????列表相當于鏈表,列表項相當于節點,FreeRTOS 中的列表是一個雙向循環鏈表 ?
????????列表項間的地址非連續的,列表項的數目隨時可以改變
????????列表項的指向前一個、后一個指針,就相當于人的左右手,整個列表就相當于N個人互相拉著手,圍成一個圈,而列表是管理這個圈
? ? ? ??
二、 列表與列表項
2.1 列表結構體
typedef struct xLIST
{listFIRST_LIST_INTEGRITY_CHECK_VALUE /* 校驗值 */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 | 具有確定已知常量的宏 FreeRTOS通過檢查這兩個常量的值,來判斷列表的數據在程序運行過程中,是否遭到破壞 ,該功能一般用于調試, 默認是不開啟的 |
uxNumberOfItems | 用于記錄列表中列表項的個數(不包含 xListEnd) |
pxIndex | 用于指向列表中的某個列表項,一般用于遍歷列表中的所有列表項 |
xListEnd | 一個迷你列表項,排在最末尾 |
列表結構示意圖:?
2.2 列表項結構體
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 /* 列表項的擁有者 */struct xLIST * configLIST_VOLATILE pxContainer; /* 列表項所在列表 */listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE /* 用于檢測列表項的數據完整性*/
};
typedef struct xLIST_ITEM ListItem_t;
成員說明:
成員 | 描述 |
listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALU | 用于檢測列表項的數據完整性 |
xItemValue | 列表項的值,多用于將列表中的列表項按升序排序 |
pxNext | 指向列表中列表項的下一個列表項 |
pxPrevious | 指向列表中列表項的上一個列表項 |
pvOwner | 用于指向包含列表項的對象(通常是任務控制塊) |
pxContainer | 用于指向列表項所在列表 |
列表項結構示意圖:?
?2.3 迷你列表項(末尾列表項)
迷你列表項也是列表項,但迷你列表項僅用于標記列表的末尾和掛載其他插入列表中的列表項(將要插入的列表項連接在一起)
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;
成員說明:?
成員 | 描述 |
listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE | 用于檢測數據完整性 |
xItemValue | 列表項的值,多用于按升序對列表中的列表項進行排序 |
pxNext pxPrevious | 用于指向列表中列表項的下一個列表項和上一個列表項 |
????????與正常列表項,缺少列表項擁有者、列表項所在列表成員 ,以節省內存開銷
迷你列表項結構示意圖:
三、列表相關API函數
函數 | 描述 |
vListInitialise() | 初始化列表 |
vListInitialiseItem() | 初始化列表項 |
vListInsertEnd() | 列表末尾插入列表項 |
vListInsert() | 列表插入列表項(升序插入) |
uxListRemove() | 列表移除列表項 |
?
3.1 初始化列表:vListInitialise( )
void vListInitialise( List_t * const pxList )
{/* 初始化時,列表中只有 xListEnd,因此 pxIndex 指向 xListEnd */pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd ); listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( &( pxList->xListEnd ) );/* xListEnd 的值初始化為最大值,用于列表項升序排序時,排在最后 */pxList->xListEnd.xItemValue = portMAX_DELAY;/* 初始化時,列表中只有 xListEnd,因此上一個和下一個列表項都為 xListEnd 本身 */pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd ); pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd ); /* 初始化時,列表中的列表項數量為 0(不包含 xListEnd) */pxList->uxNumberOfItems = ( UBaseType_t ) 0U;/* 檢查數據的完整性 */listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList );listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList );
}
參數說明:?
參數 | 說明 |
pxList | 待初始化的列表 |
列表初始化后的結構示意圖:?
3.2 列表項初始化:vListInitialiseItem()
void vListInitialiseItem( ListItem_t * const pxItem )
{/* 初始化時,列表項所在列表設為空 */pxItem->pxContainer = NULL;/* 初始化用于檢測列表項數據完整性的校驗值 */listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
}
????????其他成員變量根據實際使用情況進行初始化?
參數說明:?
參數 | 說明 |
pxItem | 待初始化的列表項 |
列表初始化后的結構示意圖:?
3.3 列表插入列表項(升序插入):vListInsert()
函數功能:將待插入列表的列表項按照列表項值升序插入,有序地插入到列表中
void vListInsert( List_t * const pxList,ListItem_t * const pxNewListItem )
{/*獲取列表項的數值依據數值升序排列 */ListItem_t * pxIterator;const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;/* 檢查參數是否正確 */listTEST_LIST_INTEGRITY( pxList );listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );/* 如果待插入列表項的值為最大值,插入的位置為列表 xListEnd 前面 */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->pxContainer = pxList;/* 更新列表中列表項的數量 */ ( pxList->uxNumberOfItems )++;
}
?參數說明:
參數 | 說明 |
pxList | 列表 |
pxNewListItem | 待插入列表項 |
3.4 列表末尾插入:?vListInsertEnd()
函數功能:將待插入列表的列表項插入到列表 pxIndex 指針指向的列表項前面(初始化時:pxIndex指向迷你列表項),是一種無序的插入方法?
void vListInsertEnd ( List_t * const pxList , ListItem_t * const pxNewListItem )
{/* 獲取列表 pxIndex 指向的列表項 */ListItem_t * const pxIndex = pxList->pxIndex;/* 更新待插入列表項的指針成員變量 */ pxNewListItem->pxNext = pxIndex; pxNewListItem->pxPrevious = pxIndex->pxPrevious;/* 更新列表中原本列表項的指針成員變量 */ pxIndex->pxPrevious->pxNext = pxNewListItem;pxIndex->pxPrevious = pxNewListItem;/* 更新待插入列表項的所在列表成員變量 */ pxNewListItem->pxContainer = pxList;/* 更新列表中列表項的數量 */( pxList->uxNumberOfItems )++;
}
參數說明:
參數 | 說明 |
pxList | 列表 |
pxNewListItem | 待插入列表項 |
2.5 移出列表項:uxListRemove()
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
{List_t * const pxList = pxItemToRemove->pxContainer; /* 從列表中移除列表項 */ pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext; /*如果 pxIndex 正指向待移除的列表項 */ if( pxList->pxIndex == pxItemToRemove ) {/*pxIndex 指向上一個列表項*/ pxList->pxIndex = pxItemToRemove->pxPrevious;} else { mtCOVERAGE_TEST_MARKER(); } /*將待移除的列表項的所在列表指針清空*/ pxItemToRemove->pxContainer = NULL; /*更新列表中列表項的數量*/ ( pxList->uxNumberOfItems )--; return pxList->uxNumberOfItems;
}
參數說明:
參數 | 說明 |
pxItemToRemove | 待移出的列表項 |
返回值 | 移除后,列表剩余的列表項數量 |