FreeRTOS 中 vListInsertEnd 函数详解

        在 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;
    

       ​​​  新列表项 pxNewListItempxNext 指向 pxIndex,即插入项的下一个项。

   pxNewListItempxPrevious 指向 pxIndex 的前一个项。

  • 更新列表中原本列表项的指针成员变量:

    pxIndex->pxPrevious->pxNext = pxNewListItem;
    pxIndex->pxPrevious = pxNewListItem;
    
    

         pxIndex 前一个项的 pxNext 更新为指向 pxNewListItem,这样链表中的前一项就指向了新插入的项。

   pxIndexpxPrevious 更新为 pxNewListItem,因此 pxIndex 的前一项变为新插入的项。

  • 更新待插入列表项的所在列表成员变量:

    pxNewListItem->pxContainer = pxList;
    
    

         pxNewListItempxContainer 设置为 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
  • listItem1pxNextpxPrevious 都指向 listItem1 自己。

例子 2: 已有多个项的列表

初始状态:

  • 列表 pxList 包含 listItem1listItem2pxIndex 指向 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, listItem3pxIndex 指向 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 可以高效管理任务和系统资源,从而确保实时操作系统的高效运行。

  • 15
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值