FreeRTOS的列表和列表项 list.c文件详解

列表、列表项的定义以及初始化

列表相当于链表,列表项相当于节点,FreeRTOS中的列表相当于一个双向环形链表。
列表使用指针指向列表项。一个列表(list)下面可能有很多个列表项(list item),每个列表项都有一个指针指向列表。
与列表相关的全部东西都在文件list.c和list.h中。在list.h中定义了一个List_t的结构体。

列表的定义

在这里插入图片描述

typedef struct xLIST
{listFIRST_LIST_INTEGRITY_CHECK_VALUE				/*用于检测列表项数据是否完整*/configLIST_VOLATILE UBaseType_t uxNumberOfItems;	/*记录列表中列表项的数量*/ListItem_t * configLIST_VOLATILE pxIndex;			/*用于遍历列表*/MiniListItem_t xListEnd;							/*列表项*/listSECOND_LIST_INTEGRITY_CHECK_VALUE				/*用于检测列表项数据是否完整*/
} List_t;
  1. 第一句和最后一句用来检查列表的完整性。
    需要将宏configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES 设置为1,开启以后会向这两个地方分别添加一个变量xListIntegrityValue1和xListIntegrityValue2,在初始化列表的时候会这两个变量中写入一个特殊的值,默认不开启这个功能。
  2. uxNumberOfItems 用来记录列表中列表项的数量。
  3. pxIndex 用来记录当前列表项索引号,用于遍历列表。
  4. 列表项中最后一个列表项,用来表示列表结束,此变量类型为MiniListItem_t,是一个迷你列表项。

列表项的定义

列表项就是存放在列表中的项目,FreeRTOS提供了两种列表项:列表项和迷你列表项。这两种都在文件list.h中有定义。

xLIST_ITEM列表项

在这里插入图片描述

struct xLIST_ITEM
{listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE			/*用于检测列表项数据是否完整*/configLIST_VOLATILE TickType_t xItemValue;			/*列表项值*/  struct xLIST_ITEM * configLIST_VOLATILE pxNext;		/*指向列表中下一个列表项*/struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;	/*指向列表中上一个列表项*/void * pvOwner;										/*指向一个任务*/void * configLIST_VOLATILE pvContainer;				/*指向包含该列表项的列表 */listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE			/*用于检测列表项数据是否完整*/
};
typedef struct xLIST_ITEM ListItem_t;
  1. 第一句和最后一句,用来检查列表项的完整性。
  2. xItemValue列表项的值。
  3. pxNext指向下一个列表项。
  4. pxPrevious指向前一个列表项,和pxNext配合起来实现类似双向链表的功能。
  5. pvOwner记录此列表项归谁拥有,通常是任务控制块。
  6. pvContainer用来记录此列表项归哪个列表。
    注意与pvOwner的区别,在TCB_t中有两个变量xStateListItem和xEventListItem,这两个变量的类型就是ListItem_t,也就是说这两个成员变量都是列表项,以xStateListItem为例,当创建一个任务以后,xStateListItem的pvOwner就指向这个任务的控制块,表示xStateListItem属于此任务。当任务就绪以后,xStateListItem的变量pvContainer就指向就绪列表,表明此列表项在就绪列表中。

xMINI_LIST_ITEM列表项

末尾列表项就是迷你列表项的一种,这里放末尾列表项的定义图。
在这里插入图片描述

struct xMINI_LIST_ITEM
{listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE			/*用于检测列表项数据是否完整*/configLIST_VOLATILE TickType_t xItemValue;struct xLIST_ITEM * configLIST_VOLATILE pxNext;struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;
};
typedef struct xMINI_LIST_ITEM MiniListItem_t;
  1. 第一句检测列表项的完整性。
  2. xItemValue记录列表列表项的值。
  3. pxNext指向下一个列表项
  4. pxPrevious指向上一个列表项
    迷你列表项比列表项少几个成员变量,迷你列表项有的成员变量,列表项都有。为什么还要使用迷你列表项呢?因为有些情况下,我们不需要这么全的功能,可能只需要其中某几个成员变量,如果此时用列表的话会造成内存浪费。例如上面列表结构体List_t中表示最后一个列表项的成员变量xListEnd 就是MiniListItem_t类型。

列表的初始化

在这里插入图片描述

如上图所示,列表初始化,列表的pxindex指向列表末尾项,把末尾的列表项初始化为最大值(0xFFFFFFFF),列表末尾项的前指针和后指针都指向它本身。下面是具体的初始化代码:

void vListInitialise( List_t * const pxList )
{/*初始化时,列表中只有xListEnd,因此pxIndex指向xListEnd*/pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd );			/*xListEnd的值初始化为最大值,用于列表项升序排序时,排在最后。*/pxList->xListEnd.xItemValue = portMAX_DELAY;/*初始化时,列表只有一个xListEnd,因此上一个和下一个列表都是它本身。*/pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd );	pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );/*初始化时,列表中的列表项数量为0(不包含xListEnd)*/pxList->uxNumberOfItems = ( UBaseType_t ) 0U;/*初始化用于检测列表数据完整性的校验值*/listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList );listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList );
}

列表项的初始化

从xLIST_ITEM列表项可知,链表节点ListItem_t 总共有5个成员,但是初始化的时候只需将pvContainer初始化为空即可。
pvContainer初始化为空表示该节点还没有插入到任何链表。
在这里插入图片描述

void vListInitialiseItem( ListItem_t * const pxItem )
{/* 初始化时,列表项所在列表设为空。 */pxItem->pvContainer = NULL;/* 初始化用于检测列表数据完整性的校验值 */listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
}

列表操作

1. 插入列表尾部

在这里插入图片描述

  1. 首先获取列表pxList中指针pxIndex 指向的列表项,如上图,如果是一个新的列表,pxIndex 指向的应该是末尾列表项。
  2. 将待插入列表项pxNewListItem的pxNext指向末尾列表项, 将待插入列表项pxNewListItem的pxPrevious 指向末尾列表项的pxPrevious。
  3. 将列表中的末尾列表项的前指向pxPrevious指向插入列表项pxNewListItem。将原来列表项前指向的对象的后指向绑定为pxNewListItem。
  4. 将添加的新列表项归属到列表中。
  5. 更新列表中列表项的数量。
void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem )
{/* 获取列表pxIndex指向的列表项 */ListItem_t * const pxIndex = pxList->pxIndex;/* 仅当同时定义了confgASSERT()时才有效,这些测试可能会捕获正在内存中覆盖的列表数据结构。它们不会捕获由于不正确配置或使用FreeRTOS而导致的数据错误. */listTEST_LIST_INTEGRITY( pxList );listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );/* 更新待插入列表项的指针成员变量 */pxNewListItem->pxNext = pxIndex;pxNewListItem->pxPrevious = pxIndex->pxPrevious;/* 仅在决策覆盖测试期间使用。*/mtCOVERAGE_TEST_DELAY();/* 更新列表中原本列表项的指针成员变量 */pxIndex->pxPrevious->pxNext = pxNewListItem;pxIndex->pxPrevious = pxNewListItem;/* 列表项的归属 */pxNewListItem->pvContainer = ( void * ) pxList;/* 更新列表中列表项的数量 */( pxList->uxNumberOfItems )++;
}

2. 升序插入列表

在这里插入图片描述

  1. 获取要添加列表项的数值,在后面用来比较排列。
  2. 根据列表项的数值,找到列表项要插入的位置,按照升序排列。如果是列表项数值为最大值,指向末尾列表项。否则,迭代找到列表项要插入的位置。然后根据升序排列,插入列表项,再将列表项加到列表里,列表的数量再加1。
  3. 如上图,是按照升序排列,将节点插入到链表。假设将一个节点排序辅助值是2的节点插入到有两个节点的链表中,这两个现有的节点的排序辅助值分别是1和3,那么插入过程的示意图具体见图。
void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem )
{ListItem_t *pxIterator;/* 获取列表项的数值,依据数值升序排列。 */const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;listTEST_LIST_INTEGRITY( pxList ); listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );	/*寻找节点要插入的位置*/if( xValueOfInsertion == portMAX_DELAY )	/* 如果待插入列表项的值为最大值 */{pxIterator = pxList->xListEnd.pxPrevious;}else{for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) {/* 没有事情可做,不断迭代只为了找到节点要插入的位置 */}}/* 根据升序排列,将节点插入 */pxNewListItem->pxNext = pxIterator->pxNext;pxNewListItem->pxNext->pxPrevious = pxNewListItem;pxNewListItem->pxPrevious = pxIterator;pxIterator->pxNext = pxNewListItem;/* 更新插入列表项的归属列表 */pxNewListItem->pvContainer = ( void * ) pxList;/* 列表中的列表项数+1 */( pxList->uxNumberOfItems )++;
}

3. 移除一个列表项

传入参数:pxItemToRemove是指向待移除的列表项的指针。
返回参数:移除后列表中列表项的数量。

  1. 首先通过指向列表项的指针获得列表项中所记录的列表信息,通过pvContainer结构体成员获得。
  2. 将(需要移除列表项)的(下一个列表项)的(前指针指向对象)指向(需要移除列表项)的(前指针指向对象)。将(需要移除列表项)的(前指针指向对象)的(后指针指向对象)指向(需要移除列表项)的(后指针指向对象)。简单地说,就是把需要移除的列表项在链表中解除指向。
  3. 如果列表正指向待移除的列表项,将其指向待移除的上一个列表项。(因为这个列表项我们要从列表中移除,所以列表不应该还能指向它。)
  4. 将待移除的列表项中的列表信息情况。(这样这个列表项就和列表没有任何关系了。)
  5. 更新列表中列表项的数目。
  6. 返回移除列表项后,列表中剩余列表项的数目。
    在这里插入图片描述
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
{/* 从列表项的pvContainer中获取列表项所在的列表 */List_t * const pxList = ( List_t * ) pxItemToRemove->pvContainer;pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;/* 仅在决策覆盖测试期间使用 */mtCOVERAGE_TEST_DELAY();/* 确保索引指向一个有效的项目 */if( pxList->pxIndex == pxItemToRemove ){pxList->pxIndex = pxItemToRemove->pxPrevious;}else{mtCOVERAGE_TEST_MARKER();}/* 列表项的列表指针指向清空 */pxItemToRemove->pvContainer = NULL;/* 列表的列表项数目-1 */( pxList->uxNumberOfItems )--;return pxList->uxNumberOfItems;
}

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

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

相关文章

vivado仿真readmemb函数相对路径

目前常用的vivado工程的结构如下所示 prj-name|-xxx|-prj.sim|-sim_1|-behav|-modelsim|-tb_prj.do|-xsim|-prj.srcs|-sim_1|-new|-tb_prj.v|-tb_prj_mem.txt一般来说我们创建的testbench文件和新建的txt文件都会放在srcs->sim_1->new这个路径下面&#xff0c;但是我们在…

【PHP【实战版】系统性学习】——登录注册页面的教程,让编写PHP注册变成一个简单的事情

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…

最美博客POETIZE个人博客系统源码

源码说明&#xff1a; POETIZE个人博客系统源码 | 最美博客 这是一个基于SpringBoot、Vue2和Vue3的开源项目&#xff0c;支持移动端自适应&#xff0c;并具备完善的前台和后台管理功能。 网站分为两个模块&#xff1a; 1. 博客系统&#xff1a;包括文章、表白墙、图片墙、收…

SpringBoot实现图片验证码

引入依赖 <dependency><groupId>com.github.whvcse</groupId><artifactId>easy-captcha</artifactId><version>1.6.2</version> </dependency>代码实现 package com.qiangesoft.captcha.controller;import com.wf.captcha.*…

【Linux】基础命令:进程、网络

systemctl命令 控制内置服务 systemctl start | stop | status | enable | disable 服务名 start | stop开启关闭&#xff0c;status状态&#xff0c;enable | disable开启关闭开机自启 date命令 查看系统时间 date [-d] [格式化字符串] date -d “1 day” %Y-%m-%d 修改时区…

Stable Diffusion:AI绘画的新纪元

摘要&#xff1a; Stable Diffusion&#xff08;SD&#xff09;作为AI绘画领域的新星&#xff0c;以其开源免费、强大的生成能力和高度的自定义性&#xff0c;正在引领一场艺术与技术的革命。本文旨在为读者提供Stable Diffusion的全面介绍&#xff0c;包括其原理、核心组件、安…

链表的经典面试题(数据结构详解)+顺序表和链表之间区别+计算机存储体系

前言 首先这里已经正式步入数据结构的知识&#xff0c;之前我们已经讲解了链表的使用&#xff0c;接下来我们需要的就是大量的练习&#xff0c;熟练掌握数据结构。下面的题型我们选择的都是链表的经典题型&#xff0c;面试题型&#xff0c;包含快慢指针&#xff0c;数形结合&am…

【qt】设计器实现界面

设计器实现界面 一.总体思路二.具体操作1.创建项目2.粗略拖放3.水平布局4.垂直布局5.修改名字6.转到槽7.实现槽函数 一.总体思路 创建项目粗略拖放水平布局垂直布局修改名称转到槽实现槽函数 二.具体操作 1.创建项目 这次咱们一定要勾选Generate form哦。 因为我们要使用设…

R语言数据探索与分析-碳排放分析预测

# 安装和加载需要的包 install.packages("readxl") install.packages("forecast") install.packages("ggplot2") library(readxl) library(forecast) library(ggplot2)# 数据加载和预处理 data <- read_excel("全年数据.xlsx") co…

感知机和神经网络

引入 什么是神经网络&#xff1f; 我们今天学习的神经网络&#xff0c;不是人或动物的神经网络&#xff0c;但是又是模仿人和动物的神经网络而定制的神经系统&#xff0c;特别是大脑和神经中枢&#xff0c;定制的系统是一种数学模型或计算机模型&#xff0c;神经网络由大量的人…

FANUC机器人工具坐标偏移的用法

一、工具坐标偏移的使用场景 在机器人位置不改变的情况下&#xff0c;工业机器人使用默认工具坐标系示教的一系列运动点位&#xff0c;要保持原本点位位置不变的情况下&#xff0c;改变机器人工具坐标的参数&#xff0c;就要用到机器人坐标转化的功能。在FANUC机器人上体现为机…

通过mvn archetype 创建一个spring boot start 工程

mvn archetype https://maven.apache.org/archetype/index.html 遇到的问题 对于想自定义一个spring-boot-start的同学,比如 Springboot自定义Starter启动器 整个过程很繁琐。 定义属性开关增加 spring boot test start插件定义自动装载 spring.factories or org.springfra…

关于一致性,你该知道的事儿(上)

关于一致性&#xff0c;你该知道的事儿&#xff08;上&#xff09; 前言一、缓存一致性二、内存模型一致性三、事务一致性四、分布式事务一致性4.1 分布式系统的一些挑战4.2 关于副本的一些概念4.3 分布式事务之共识问题4. 3.1 PC(two-phase commit, 2PC)4.3.2 Raft 三、后记参…

【牛客】SQL201 查找薪水记录超过15条的员工号emp_no以及其对应的记录次数t

1、描述 有一个薪水表&#xff0c;salaries简况如下&#xff1a; 请你查找薪水记录超过15条的员工号emp_no以及其对应的记录次数t&#xff0c;以上例子输出如下&#xff1a; 2、题目建表 drop table if exists salaries ; CREATE TABLE salaries ( emp_no int(11) NOT N…

python数据分析——pandas数据结构2

参考资料&#xff1a;活用pandas库 导入基础数据 # 导入库 import pandas as pd # 读取数据集 dfpd.read_csv(r"..\data\scientists.csv") df.head() 1、DataFrame DataFrame是Pandas中最常见的对象。可以把它看作python存储电子表格式数据的方式。Series数据结构…

基于单片机的温度控制系统设计(51基础版)-设计说明书

本论文设计了一种基于51单片机的温度控制系统&#xff0c;该系统具备以下主要功能&#xff1a;首先&#xff0c;通过温度传感器实时检测环境温湿度&#xff0c;以获取准确的温度数值。其次&#xff0c;通过按键设置温度阈值&#xff0c;用户可以根据需求自行调整控制温度的上限…

Dragonfly 拓扑的路由算法

Dragonfly 拓扑的路由算法 1. Dragonfly 上的路由 (1)最小路由(2)非最小路由 2. 评估3. 存在问题 (1)吞吐量限制(2)较高的中间延迟 references Dragonfly 拓扑的路由算法 John Kim, William J. Dally 等人在 2008 年的 ISCA 中提出技术驱动、高度可扩展的 Dragonfly 拓扑。而…

杰发科技AC7801——ADC之Bandgap和内部温度计算

0. 参考 电流模架构Bandgap设计与仿真 bandgap的理解&#xff08;内部带隙电压基准&#xff09; ​ ​ 虽然看不懂这些公式&#xff0c;但是比较重要的一句应该是这个&#xff1a;因为传统带隙基准的输出值为1.2V ​ 1. 使用 参考示例代码。 40002000是falsh控制器寄…

从离线到实时:无锡锡商银行基于 Apache Doris 的数据仓库演进实践

作者&#xff1a;武基鹏&#xff0c;无锡锡商银行 大数据技术经理 编辑整理&#xff1a;SelectDB 技术团队 导读&#xff1a;为实现数据资产的价值转化以及全面数字化、智能化的风险管理&#xff0c;无锡锡商银行大数据平台经历从 Hive 离线数据仓库到 Apache Doris 实时数据仓…

鸿蒙ArkUI-X跨平台开发电商应用

一、ArkUI-X 简介 ArkUI-X 是由 OpenHarmony TSC - 跨平台应用开发框架 TSG 所孵化的开源项目,使用ArkUI-X可以让开发者基于一套主代码, 就可以构建支持多平台的精美、高性能应用。目前支持OpenHarmony、HarmonyOS、Android、 iOS,后续会逐步增加更多平台支持。 ArKUI跨平台…