????????在 FreeRTOS 中,vListInsertEnd
函數用于將新項插入到指定列表的尾部(但實際行為是插入到一個特定的索引位置之前)。FreeRTOS 使用雙向鏈表(doubly linked list)來管理任務和其他系統對象,這樣可以高效地插入、刪除和遍歷列表。
1. vListInsertEnd
函數源碼解析
vListInsertEnd
函數將新項插入到列表中 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 )++;
}
2. 代碼詳解
-
獲取列表
pxIndex
指向的列表項:ListItem_t * const pxIndex = pxList->pxIndex;
pxIndex
是一個指向列表中某一項的指針。該項將作為新項插入位置的參考點。 -
更新待插入列表項的指針成員變量:
pxNewListItem->pxNext = pxIndex; pxNewListItem->pxPrevious = pxIndex->pxPrevious;
? ? ? ????? 新列表項 pxNewListItem
的 pxNext
指向 pxIndex
,即插入項的下一個項。
? ?pxNewListItem
的 pxPrevious
指向 pxIndex
的前一個項。
-
更新列表中原本列表項的指針成員變量:
pxIndex->pxPrevious->pxNext = pxNewListItem; pxIndex->pxPrevious = pxNewListItem;
? ? ? ? ?pxIndex
前一個項的 pxNext
更新為指向 pxNewListItem
,這樣鏈表中的前一項就指向了新插入的項。
? ?pxIndex
的 pxPrevious
更新為 pxNewListItem
,因此 pxIndex
的前一項變為新插入的項。
-
更新待插入列表項的所在列表成員變量:
pxNewListItem->pxContainer = pxList;
? ? ? ? ?pxNewListItem
的 pxContainer
設置為 pxList
,表示該項屬于這個列表
-
更新列表中列表項的數量:
( pxList->uxNumberOfItems )++;
????????列表的項數增加一。
3. 實例分析
以下是 vListInsertEnd
函數的幾個示例,以幫助理解其工作原理。
例子 1: 空列表
初始狀態:
- 列表
pxList
為空,pxIndex
指向列表頭。
List_t list;
ListItem_t listItem1;// 初始化列表
list.pxIndex = &listItem1;
list.uxNumberOfItems = 0;// 插入新項
vListInsertEnd(&list, &listItem1);
插入后:
pxList
現在包含一項listItem1
。listItem1
的pxNext
和pxPrevious
都指向listItem1
自己。
例子 2: 已有多個項的列表
初始狀態:
- 列表
pxList
包含listItem1
、listItem2
,pxIndex
指向listItem2
。
List_t list;
ListItem_t listItem1, listItem2, listItem3;// 初始化列表
list.pxIndex = &listItem2;
list.uxNumberOfItems = 2;listItem1.pxNext = &listItem2;
listItem1.pxPrevious = &listItem2;listItem2.pxNext = &listItem1;
listItem2.pxPrevious = &listItem1;// 插入新項
vListInsertEnd(&list, &listItem3);
插入后:
listItem3
被插入到listItem2
前。- 列表順序為:
listItem1 -> listItem3 -> listItem2
。
例子 3: 插入到非尾部
初始狀態:
- 列表
pxList
包含listItem1
,listItem2
,listItem3
,pxIndex
指向listItem2
。
List_t list;
ListItem_t listItem1, listItem2, listItem3, listItem4;// 初始化列表
list.pxIndex = &listItem2;
list.uxNumberOfItems = 3;listItem1.pxNext = &listItem2;
listItem1.pxPrevious = &listItem3;listItem2.pxNext = &listItem3;
listItem2.pxPrevious = &listItem1;listItem3.pxNext = &listItem1;
listItem3.pxPrevious = &listItem2;// 插入新項
vListInsertEnd(&list, &listItem4);
插入后:
listItem4
被插入到listItem2
前。- 列表順序為:
listItem1 -> listItem4 -> listItem2 -> listItem3
。
4. 適用場景
- 任務調度:在 FreeRTOS 中,任務可以被插入到就緒任務列表中以表示它們可以運行。
- 時間管理:延遲任務可以插入到延遲列表中,以便當時間到達時,任務會被恢復。
- 資源管理:可以用于管理隊列、信號量等對象的列表。
??vListInsertEnd
是 FreeRTOS 中用于在列表中插入新項的函數。雖然名稱暗示插入到末尾,但實際功能是插入到 pxIndex
指向項的前面。函數通過更新指針來維持雙向鏈表的完整性,同時增加列表項的數量。這種結構使得 FreeRTOS 可以高效管理任務和系統資源,從而確保實時操作系統的高效運行。