FreeRTOS之链表源码分析

文章目录


前言

① 本文章学习完韦东山老师的 《freeRTOS系列教程:FreeRTOS的内部机制》之后做的总结。大家可前往看视频。

② 代码是云途芯片的SDK,关于FreeRTOS的源码都大同小异,无需纠结。

韦东山freeRTOS系列教程:FreeRTOS的内部机制

一、结构体

1、链表List_t

  • uxNumberOfItems:表示该链表下有多少个链表节点(例如:优先级为1的任务都存在链表pxReadyTaskLists1中,uxNumberOfItems 等于 2,表示有两个优先级为1的任务在Ready链表中等待)
  • pxIndex:指向当前正在使用的链表项item,这个pxIndex被用来遍历链表。
  • xListEnd:是一个MiniListItem_t节点,是链表的最后一个节点。因为FreeRTOS定义的链表是循环双向链表,因此xListEnd也是链表的第一节点。

2、链表项xLIST_ITEM

  • xItemValue:每个链表项(节点)的一个计数值,一般用来做排序。(比如把链表中的节点都按序排列,就离不开它)
  • pxNext:指向后继节点。
  • pxPrevious:指向前一个节点。
  • pvOwner:指向拥有该节点的内核对象,一般是指TCB结构体。
  • pxContainer:指向节点所在的链表xLIST。

3、头节点xMINI_LIST_ITEM

  • xItemValue:每个链表项(节点)的一个计数值,一般用来做排序。(比如把链表中的节点都按序排列,就离不开它)
  • pxNext:指向后继节点。
  • pxPrevious :指向前一个节点。
    (这个链表项比上面的链表项少了pvOwner和pxContainer,可以把它当成链表中的头节点/尾节点xListEnd)

4、链表示意图

在上图中,链表中元素是顺序是:item1、item2、item3、xListEnd。

list中有一个pxIndex,指向当前真在使用的item。链表的遍历过程如下:

  • pxIndex初始时指向链表list中的xListEnd(数据类型MiniListItem_t)
  • 要取出第一个元素时,pxIndex就会指向item1
  • 再取出下一个元素时,pxIndex就会指向item2
  • 再取出下一个元素时,pxIndex就会指向item3
  • 再取出下一个元素时,pxIndex就会指向xListEnd
  • 发现它是xListEnd时,继续去下一个元素,pxIndex就会指向item1

~

二、函数分析

1、初始化函数vListInitialise

List_t中有一个Item: xListEnd,初始化链表后,结果如下:

  • uxNumberOfItems等于0,表示链表尾空,链表项的数量为0。
  • pxIndex指向xListEnd。
  • xListEnd中的pxNext、pxPrevious指向xListEnd(表示链表是空的)。
  • xListEnd中的xItemValue等于portMAX_DELAY。
    可以用下图来简述:

2、初始化链表项vListInitialiseItem

pxContainer指向节点所在的链表xLIST为NULL,表示不存在于任何链表。

3、链表尾部添加节点vListInsertEnd


① pxIndex = pxList->pxIndex ; 指向当前正在使用的节点itme2(若链表是空的,那么就是指向xListEnd头节点)
② pxNewListItem->pxNext = pxIndex ; 新增节点item4的下一个节点是当前正在使用的节点itme2(若链表是空的,那么就是指向xListEnd头节点)
③ pxNewListItem->pxPrevious = pxIndex->pxPrevious ;新增节点item4的上一个节点是当前正在使用的节点itme2的前节点item1(若链表是空的,那么就是指向xListEnd头节点)
④ pxIndex->pxPrevious->pxNext = pxNewListItem ;当前正在使用的节点itme2的前节点item1的后继节点是新增节点item4(若链表是空的,那么就是xListEnd头节点指向后继节点是新增节点item4)
⑤ pxIndex->pxPrevious = pxNewListItem ; 当前正在使用的节点itme2的前一节点是item4(若链表是空的,那么就是xListEnd头节点指向前一个结点是新增节点item4)
⑥ pxNewListItem->pxContainer = pxList; 新插入节点item4指向节点所在的链表pxList.

看下图更好理解:

① 所谓的尾部并不是指链表中的尾部节点,而是指插入到pxIndex指向的item2节点之前。

(Tips:因为pxIndex指向的节点表示正在使用的节点,item2使用完之后,pxIndex指向item3,接着再pxIndex指向item1。这样插入结点之后,item4就是最后一个被使用的节点。)

4、按序插入节点vListInsert


① for循环中,当pxIterator指向item2的时候,退出循环。
② pxNewListItem->pxNext = pxIterator->pxNext; 新节点item4的后继节点是item2的后继节点item3
③ pxNewListItem->pxNext->pxPrevious = pxNewListItem; 新节点item4的后继节点item3的前一节点指向新节点item4
④ pxNewListItem->pxPrevious = pxIterator; 新节点item4的前一节点是item2(pxIterator指向的节点,来源于for循环的遍历结果)
⑤ pxIterator->pxNext = pxNewListItem; item2的后继节点是新节点item4
⑥ 如果是初始值portMAX_DELAY,那就加入到最后一个位置,即xListEnd的前一项。(下面代码段)

c 复制代码
if( xValueOfInsertion == portMAX_DELAY )
    {
        pxIterator = pxList->xListEnd.pxPrevious;
    }

看下图更好理解:

怎么插入呢?
a)先找到位置item

item(item2)->xItemValue < item_new(item4)->xItemValue

item(item3)->next(item3)->xItemValue < item_new(item4)->xItemValue
b)在item2之后插入

~

5、删除节点uxListRemove


① pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious ; 删除项item2后继节点(item3)的前一结点是删除项item2的前一节点(item1)。
② pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext ; 删除项item2前一节点(item1)的后继节点是item2的后继节点(item3)
③ 如果删除项item2正处于被使用状态时候,就将索引指针pxList->pxIndex指向item2的前一节点(item1)
④ pxItemToRemove->pxContainer = NULL; item2都被删除啦,所以它的链表信息应该也被删除。

c 复制代码
if( pxList->pxIndex == pxItemToRemove )
    {
        pxList->pxIndex = pxItemToRemove->pxPrevious;
    }

⑤ ( pxList->uxNumberOfItems ) = ( UBaseType_t ) ( pxList->uxNumberOfItems - 1U ); 链表中的节点个数减1

看下图更好理解:

~

总结

博主是小白,刚开始接触FreeRTOS,如果哪里表达的有问题,还请大佬们指点指点哈。接下来,让我们在后面的博文再相会哈~

相关推荐
yi0118 小时前
LeetCode 219:存在重复元素 II——哈希表记录“最近一次出现的位置”
数据结构·人工智能·笔记·python·算法·leetcode·哈希表
Jason_zhao_MR9 小时前
Linux与实时控制如何兼得
linux·嵌入式硬件·机器人·工业控制
BSD_CGQ10 小时前
FSR传感器STM32 DMA高速采样工程实现(高精度、低CPU占用)
stm32·单片机·嵌入式硬件·压力传感器·源头工厂·柔性薄膜压力传感器·可变电阻压力传感器
Escalating_xu11 小时前
【C 语言】数据在内存中的存储:补码、大小端、整型陷阱与 IEEE 754 全解析
java·c语言·网络
禾小西11 小时前
Redis 数据结构:快速的 Redis 有哪些慢操作?
数据结构·数据库·redis
H.莓飛11 小时前
【数据结构】二叉树_OJ题
linux·开发语言·数据结构·算法
好想像大佬一样能够ak所有12 小时前
Leetcode35.搜索插入位置
数据结构·算法·leetcode
chenbingjie_c13 小时前
C++ STL 适配器:stack & queue,从 vector/list 到 deque 深度解析
数据结构·c++
芯岭技术郦13 小时前
32 位 ARM® Cortex®-M0+ 内核MCU普冉MS32C001-C
单片机·嵌入式硬件
骑着毛驴数星星13 小时前
STM32 CAN波特率与采样点计算,基于HAL库
stm32·单片机·嵌入式硬件