FreeRTOS之链表源码分析

文章目录

  • 前言
  • 一、结构体
    • 1、链表List_t
    • 2、链表项xLIST_ITEM
    • 3、头节点xMINI_LIST_ITEM
    • 4、链表示意图
  • 二、函数分析
    • 1、初始化函数vListInitialise
    • 2、初始化链表项vListInitialiseItem
    • 3、链表尾部添加节点vListInsertEnd
    • 4、按序插入节点vListInsert
    • 5、删除节点uxListRemove
  • 总结


前言

① 本文章学习完韦东山老师的 《freeRTOS系列教程:FreeRTOS的内部机制》之后做的总结。大家可前往看视频。
② 代码是云途芯片的SDK,关于FreeRTOS的源码都大同小异,无需纠结。

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

一、结构体

1、链表List_t

在这里插入图片描述

  • uxNumberOfItems:表示该链表下有多少个链表节点(例如:优先级为1的任务都存在链表pxReadyTaskLists[1]中,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

新建一个PwmFtm_0,
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的前一项。(下面代码段)

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都被删除啦,所以它的链表信息应该也被删除。

if( pxList->pxIndex == pxItemToRemove ){pxList->pxIndex = pxItemToRemove->pxPrevious;}

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

看下图更好理解:
在这里插入图片描述

~

总结

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/478516.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【深度学习】【RKNN】【C++】模型转化、环境搭建以及模型部署的详细教程

【深度学习】【RKNN】【C】模型转化、环境搭建以及模型部署的详细教程 提示:博主取舍了很多大佬的博文并亲测有效,分享笔记邀大家共同学习讨论 文章目录 【深度学习】【RKNN】【C】模型转化、环境搭建以及模型部署的详细教程前言模型转换--pytorch转rknnpytorch转onnxonnx转rkn…

Matlab 深度学习工具箱 案例学习与测试————求二阶微分方程

clc clear% 定义输入变量 x linspace(0,2,10000);% 定义网络的层参数 inputSize 1; layers [featureInputLayer(inputSize,Normalization"none")fullyConnectedLayer(10)sigmoidLayerfullyConnectedLayer(1)sigmoidLayer]; % 创建网络 net dlnetwork(layers);% 训…

51单片机-独立按键与数码管联动

独立键盘和矩阵键盘检测原理及实现 键盘的分类&#xff1a;编码键盘和非编码键盘 键盘上闭合键的识别由专用的硬件编码器实现&#xff0c;并产生键编码号或键值的称为编码键盘&#xff0c;如&#xff1a;计算机键盘。靠软件编程识别的称为非编码键盘&#xff1b;在单片机组成…

华为无线AC+AP组网实际应用小结

之前公司都是使用的H3C的交换机、防火墙以及无线AC和AP的&#xff0c;最近优化下无线网络&#xff0c;说新的设备用华为的&#xff0c;然后我是直到要部署的当天才知道用华为设备的&#xff0c;就很无语了&#xff0c;一点准备没有&#xff0c;以下为这次的实际操作记录吧&…

浅谈网络 | 传输层之TCP协议

目录 TCP 包头格式TCP 的三次握手TCP 的四次挥手TCP 的可靠性与"靠谱"的哲学TCP流量控制TCP拥塞控制 上一章我们提到&#xff0c;UDP 就像我们小时候一样简单天真&#xff0c;它相信“网之初&#xff0c;性本善&#xff0c;不丢包&#xff0c;不乱序”&#xff0c;因…

MongoDB相关问题

视频教程 【GeekHour】20分钟掌握MongoDB Complete MongoDB Tutorial by Net Ninja MongoDB开机后调用缓慢的原因及解决方法 问题分析&#xff1a; MongoDB开机后调用缓慢&#xff0c;通常是由于以下原因导致&#xff1a; 索引重建&#xff1a; MongoDB在启动时会重建索引…

嵌入式驱动开发详解3(pinctrl和gpio子系统)

文章目录 前言pinctrl子系统pin引脚配置pinctrl驱动详解 gpio子系统gpio属性配置gpio子系统驱动gpio子系统API函数与gpio子系统相关的of函数 pinctrl和gpio子系统的使用设备树配置驱动层部分用户层部分 前言 如果不用pinctrl和gpio子系统的话&#xff0c;我们开发驱动时需要先…

[模版总结] - 树的基本算法4 -最近公共祖先 LCA

什么是最近公共祖先LCA LCA&#xff1a;在一个树中&#xff0c;距离两个节点p,q最近可以是其本身并且同时包含这两个子节点的节点 题目连接 Leetcode 236 - LCA Leetcode 1644 - LCA II Leetcode 1650 - LCAIII Leetcode 1123 - LCA of Deepest leaves 基本思路 Leetcode 23…

永磁同步电机末端振动抑制(输入整形)

文章目录 1、前言2、双惯量系统3、输入整形3.1 ZV整形器3.2 ZVD整形器3.3 EI整形器 4、伺服系统位置环控制模型5、仿真5.1 快速性分析5.2 鲁棒性分析 参考 1、前言 什么是振动抑制&#xff1f;对于一个需要精确定位的系统&#xff0c;比如机械臂、塔吊、码头集装箱等&#xff…

jQuery-Word-Export 使用记录及完整修正文件下载 jquery.wordexport.js

参考资料&#xff1a; jQuery-Word-Export导出word_jquery.wordexport.js下载-CSDN博客 近期又需要自己做个 Html2Doc 的解决方案&#xff0c;因为客户又不想要 Html2pdf 的下载了&#xff0c;当初还给我费尽心思解决Html转pdf时中文输出的问题&#xff08;html转pdf文件下载之…

【Redis_Day6】Hash类型

【Redis_Day6】Hash类型 Hash类型操作hash的命令hset&#xff1a;设置hash中指定的字段&#xff08;field&#xff09;的值&#xff08;value&#xff09;hsetnx&#xff1a;想hash中添加字段并设置值hget&#xff1a;获取hash中指定字段的值hexists&#xff1a;判断hash中是否…

【CSP CCF记录】201809-2第14次认证 买菜

题目 样例输入 4 1 3 5 6 9 13 14 15 2 4 5 7 10 11 13 14 样例输出 3 思路 易错点&#xff1a;仅考虑所给样例&#xff0c;会误以为H和W两人的装车时间是一一对应的&#xff0c;那么提交结果的运行错误就会让你瞬间清醒。 本题关键是认识到H和W的装车时间不一定一一对应&…

Unity清除所有的PlayerPrefs

方法1&#xff1a; 直接在你的代码中加入这句 PlayerPrefs.DeleteAll(); 方法2&#xff1a; 点击编辑窗口的这里

非交换几何与黎曼ζ函数:数学中的一场革命性对话

非交换几何与黎曼ζ函数&#xff1a;数学中的一场革命性对话 非交换几何&#xff08;Noncommutative Geometry, NCG&#xff09;是数学的一个分支领域&#xff0c;它将经典的几何概念扩展到非交换代数的框架中。非交换代数是一种结合代数&#xff0c;其中乘积不是交换性的&…

微信小程序下拉刷新与上拉触底的全面教程

微信小程序下拉刷新与上拉触底的全面教程 引言 在微信小程序的开发中,用户体验至关重要。下拉刷新和上拉触底是提高用户交互体验的重要功能,能够让用户轻松获取最新数据和内容。本文将详细介绍这两个功能的实现方式,结合实际案例、代码示例和图片展示,帮助开发者轻松掌握…

数据库的联合查询

数据库的联合查询 简介为什么要使⽤联合查询多表联合查询时MYSQL内部是如何进⾏计算的构造练习案例数据案例&#xff1a;⼀个完整的联合查询的过程 内连接语法⽰例 外连接语法 ⽰例⾃连接应⽤场景示例表连接练习 ⼦查询语法单⾏⼦查询多⾏⼦查询多列⼦查询在from⼦句中使⽤⼦查…

论文阅读:A fast, scalable and versatile tool for analysis of single-cell omics data

Zhang, K., Zemke, N.R., Armand, E.J. et al. A fast, scalable and versatile tool for analysis of single-cell omics data. Nat Methods 21, 217–227 (2024). 论文地址&#xff1a;https://doi.org/10.1038/s41592-023-02139-9 代码地址&#xff1a;https://github.com…

Hive离线数仓结构分析

Hive离线数仓结构 首先&#xff0c;在数据源部分&#xff0c;包括源业务库、用户日志、爬虫数据和系统日志&#xff0c;这些都是数据的源头。这些数据通过Sqoop、DataX或 Flume 工具进行提取和导入操作。这些工具负责将不同来源的数据传输到基于 Hive 的离线数据仓库中。 在离线…

设计模式之 模板方法模式

模板方法模式是行为型设计模式的一种。它定义了一个算法的骨架&#xff0c;并将某些步骤的实现延迟到子类中。模板方法模式允许子类在不改变算法结构的情况下重新定义算法的某些特定步骤。 模板方法模式的核心在于&#xff1a; 封装算法的骨架&#xff1a;通过父类中的模板方…

【分治】--- 快速选择算法

Welcome to 9ilks Code World (๑•́ ₃ •̀๑) 个人主页: 9ilk (๑•́ ₃ •̀๑) 文章专栏&#xff1a; 算法Journey &#x1f3e0; 颜色划分 &#x1f4cc; 题目解析 颜色分类 本题要求我们原地对元数组划分0,1,2三个区域,也就是不能使用辅助数组&#xf…