freertos双向链表的插入


        uxTopReadyPriority = uxTopReadyPriority | (1UL<<pxNewTCB->uxPriority);

        
        //listINSERT_END( &pxReadyTasksLists[pxNewTCB->uxPriority], &pxNewTCB->xStateListItem );

        


        List_t *pxList_;          //指向目标优先级的就绪任务列表 (通过TCB的优先级索引)
        ListItem_t *pxListItem_;  //是待插入的任务状态列表项 (来自TCB的xStateListItem)    
        pxList_ = &pxReadyTasksLists[pxNewTCB->uxPriority];
        pxListItem_ = &pxNewTCB->xStateListItem;        
        ListItem_t * const pxIndex = pxList_->pxIndex;  //是列表的遍历指针 (通常指向列表末尾)
        
        /* Insert a new list item into ( pxList ), but rather than sort the list,     
         * makes the new list item the last item to be removed by a call to           
         * listGET_OWNER_OF_NEXT_ENTRY(). */                                          
        pxListItem_->pxNext = pxIndex;                  // 新项的next指向当前索引项                                       
        pxListItem_->pxPrevious = pxIndex->pxPrevious;  // 新项的prev指向索引项的前驱                            
                                                                                      
        pxIndex->pxPrevious->pxNext = pxListItem_;      // 前驱项的next指向新项                            
        pxIndex->pxPrevious = pxListItem_;              // 索引项的prev指向新项   

        //Remember which list the item is in.                                     
        pxListItem_->pxContainer = pxList_;    //记录所属列表  (用于后续从列表移除)                                   
        pxList_->uxNumberOfItems++;            //更新列表长度计数器
        portSETUP_TCB(pxNewTCB);


        //                  [原有节点]     ↔ [pxIndex节点]
        //形成环形链表结构:[原有节点] ↔ [新节点] ↔ [pxIndex节点]

        //             volatile UBaseType_t uxNumberOfItems = 0  //链表中元素的个数
        //    |<---- ListItem_t *pxIndex;                       //总是指向xListEnd节点,在链表尾部插入的时候,方便找到位置    
        //|-->|----> TickType_t xItemValue = portMAX_DELAY     [MiniListItem_t xListEnd]   
        //|<-------- struct xLIST_ITEM *pxNext;                //后继节点
        //|<-------- struct xLIST_ITEM *pxPrevious;            //前驱节点    

        //|------->volatile UBaseType_t uxNumberOfItems = 1    //链表中元素的个数
        //| |<-----ListItem_t *pxIndex;                           //总是指向xListEnd节点,在链表尾部插入的时候,方便找到位置    
        //| |->|-->TickType_t xItemValue = portMAX_DELAY       [MiniListItem_t xListEnd]   
        //|    |   struct xLIST_ITEM *pxNext;     ----->|      //后继节点
        //|    |   struct xLIST_ITEM *pxPrevious; ----->|      //前驱节点    
        //|    |                                        |
        //|    |   TickType_t xItemValue; <-------------|      //链表节点的值
        //|    |<--struct xLIST_ITEM *pxNext;                  //后继节点
        //|    |<--struct xLIST_ITEM *pxPrevious;              //前驱节点
        //|        void * pvOwner;                             //保存私有数据
        //|<------ struct xLIST *pxContainer;                  //节点所在的链表
                                                                   
        //|------->volatile UBaseType_t uxNumberOfItems = 2    //链表中元素的个数
        //| |<-----ListItem_t *pxIndex;                           //总是指向xListEnd节点,在链表尾部插入的时候,方便找到位置    
        //| |->|-->TickType_t xItemValue = portMAX_DELAY       [MiniListItem_t xListEnd]   
        //|    |   struct xLIST_ITEM *pxNext; ---->|           //后继节点
        //|    |   struct xLIST_ITEM *pxPrevious;--|----->|    //前驱节点    
        //|    |                                   |      |       
        //|  |-|-->TickType_t xItemValue; <--------|      |    //链表节点的值
        //|  | |   struct xLIST_ITEM *pxNext; ----------->|    //后继节点
        //|  | |<--struct xLIST_ITEM *pxPrevious;         |    //前驱节点
        //|  | |   void * pvOwner;                        |    //保存私有数据
        //|<-|-|---struct xLIST *pxContainer;             |    //节点所在的链表
        //|  | |                                          |                     
        //|  | |   TickType_t xItemValue;   <-------------|    //链表节点的值
        //|  | |<--struct xLIST_ITEM *pxNext;                  //后继节点
        //|  |<----struct xLIST_ITEM *pxPrevious;              //前驱节点
        //|        void * pvOwner;                             //保存私有数据
        //|<------ struct xLIST *pxContainer;                  //节点所在的链表
        

        


    
        

### FreeRTOS双向链表的实现 #### 数据结构 FreeRTOS 使用 `struct xLIST_ITEM` 定义了链表节点,每个节点包含几个重要成员变量: - `volatile unsigned int xItemValue`: 节点的关键字值。 - `struct xLIST_ITEM * pxNext`: 指向下一个节点的指针。 - `struct xLIST_ITEM * pxPrevious`: 指向上一个节点的指针。 - `void * pvOwner`: 指向该节点所属对象的指针。 - `struct xLIST * pxContainer`: 指向该节点所在链表的指针。 这些字段共同构成了一个完整的双向链表节点[^5]。 ```c typedef struct xLIST_ITEM { volatile unsigned int xItemValue; struct xLIST_ITEM *pxNext; struct xLIST_ITEM *pxPrevious; void *pvOwner; struct xLIST *pxContainer; } ListItem_t; ``` 除了单个节点外,还有一个表示整个列表的数据结构 `xList`: ```c typedef struct xLIST { struct xMINI_LIST_ITEM *pxIndex; uint8_t ucPadding1[ ( portALIGNMENT_SIZE - sizeof( struct xMINI_LIST_ITEM * ) ) & ( portBYTE_ALIGNMENT_MASK ) ]; ListItem_t xListEnd; char ucPadding2[portITEM_SIZE]; } List_t; ``` 其中 `xListEnd` 是一个特殊的哨兵节点,用来简化边界条件处理[^3]。 #### 初始化函数 为了创建并初始化一个新的链表实例,提供了如下接口: ```c void vListInitialise(List_t * const pxList); ``` 此方法会设置初始状态下的前驱和后继关系,并将所有其他属性置为空或默认值。 对于单独的链表项,则有对应的初始化过程: ```c void vListInitialiseItem(ListItem_t * const pxItem); ``` 这一步骤主要是清除可能存在的残留连接信息,确保新加入的项目处于干净的状态。 #### 插入操作 当需要往已有的有序序列里添加新的元素时,可以调用下面的方法之一来完成这项工作: ##### 尾部追加 如果希望把目标条目附加到现有集合最后面的位置上,那么应该采用这种方式来进行扩展: ```c void listSET_END_MARKER(ListItem_t * const pxItemToSet, List_t * const pxList); ``` 不过更常用的是通过遍历找到合适位置后再执行插入动作。此时就需要借助于比较逻辑以及迭代器的帮助了。 ##### 排序插入 按照指定顺序排列新增记录的最佳实践是利用内置辅助工具——`prvInsert`(私有函数),它负责寻找恰当之处并将待处理单元放置进去: ```c static void prvInsert( List_t * const pxList, ListItem_t * const pxNewListItem ); ``` 上述代码片段展示了如何高效地维护一个始终保持着特定次序不变的动态容器。 #### 移除功能 一旦某个实体不再被需求保留下来,就可以安全地将其从当前关联组中剔除出去: ```c void vListRemove(ListItem_t * const pxItemToRemove); ``` 值得注意的是,在实际应用过程中往往还需要额外注意同步控制等问题以防止竞争状况的发生。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值