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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JavaEE技术之MySql主从复制及mycat[了解,不讲]

文章目录 1. 主从复制1.1. 主从同步的原理1.2. 检查数据库远程访问权限1.3. 主从配置1.3.1. master配置1.3.2. slave配置1.3.3. 主库创建同步用户1.3.4. 从库配置主从关系1.3.5. 重置主从关系 1.4. 测试主从复制 2. Mycat2.1. Mycat简介2.2. MyCat读写分离原理2.3. 不废话&…

Linux NFS共享目录配置漏洞

Linux NFS共享目录配置漏洞 一、实验目的二、实验原理三、复现准备四、漏洞复现4.1、复现前提4.2、正式复现 一、实验目的 利用 NFS共享目录配置漏洞读取目标主机的 /etc/passwd 文件内容NFS 服务配置漏洞&#xff0c;赋予了根目录远程可写权限&#xff0c;导致 /root/.ssh/au…

编写Ansible角色实现分布式LNMP安装

前言 本文将介绍如何使用 Ansible 编写角色&#xff0c;在分布式环境下完成 LNMP&#xff08;Linux、Nginx、MySQL、PHP&#xff09;的自动化&#xff08;编译&#xff09;安装和配置&#xff0c;并验证 PHP 与 MySQL 数据联通性&#xff0c;实现博客和论坛页面的展示。 常规…

初识C语言——第十八天

循环while/do while while 语法结构 while(表达式) 循环语句; break:在while循环中&#xff0c;break用于永久的终止循环 continue:在while循环中&#xff0c;continue的作用是跳过本次循环continue后面的代码 直接去判断部分&#xff0c;看是否进行下一次循环。 注意事项…

情感感知OCR:整合深度学习技术提升文字识别系统的情感理解能力

摘要&#xff1a;随着深度学习技术的发展&#xff0c;文字识别&#xff08;OCR&#xff09;系统在识别准确率和速度上取得了长足的进步。然而&#xff0c;在处理文本时&#xff0c;仅仅依靠字符和词语的识别并不足以满足用户对信息的全面理解需求。本文提出了一种新颖的方法&am…

nacos命名空间的配置

给微服务配置namespace 给微服务配置namespace只能通过修改配置来实现。 例如&#xff0c;修改order-service的application.yml文件&#xff1a; spring:cloud:nacos:server-addr: localhost:8848discovery:cluster-name: HZnamespace: 492a7d5d-237b-46a1-a99a-fa8e98e4b0f…

sscanf字符串解析

ATCIPSNTPTIME? //发生的指令 CIPSNTPTIME:Tue Oct 19 15:17:56 2021 //回复的数据 //接受数据缓存 char* recvStrBuf "CIPSNTPTIME:Tue Oct 19 15:17:56 2021"; char* weekStr; char* monthStr; int day,hour,minute,second,year; sscanf(recvStrBuf,""…

【效率开发】游戏开发Debug效率方法总结

"程序员的一半生命都浪费在了调试上。" ——Brian Kernighan&#xff08;计算机科学家&#xff0c;曾参与开发C语言&#xff09; &#xff08;图片来源&#xff1a;forbesindia&#xff09; Debug无疑是程序员最头疼&#xff0c;也是耗费时间最多的一个环节&#xf…

redis抖动问题导致延迟或者断开的处理方案

目录&#xff1a; 1、使用背景2、redis重试机制3、redis重连机制4、其他一些解决redis抖动问题方案 1、使用背景 客户反馈文件偶现打不开&#xff0c;报错现象是session not exist&#xff0c;最终定位是redis抖动导致的延迟/断开的现象&#xff0c;最终研发团方案是加入redis…

紫光计算机项目卓越中心负责人孙宇受邀为第十三届中国PMO大会演讲嘉宾

全国PMO专业人士年度盛会 紫光计算机科技有限公司信息技术中心项目总监&卓越中心负责人孙宇先生受邀为PMO评论主办的2024第十三届中国PMO大会演讲嘉宾&#xff0c;演讲议题为“PMO卓越中心核心能力拆解与落地-用创新绘制新蓝图”。大会将于6月29-30日在北京举办&#xff0c…

docker安装向量数据库milvus

Miluvs Milvus 向量数据库能够帮助用户轻松应对海量非结构化数据(图片 / 视频 / 语音 / 文本)检索。 单节点 Milvus 可以在秒内完成十亿级的向量搜索,分布式架构亦能满足用户的水平扩展需求。 Milvus 向量数据库的应用场景包括:互联网娱乐(图片搜索 / 视频搜索)、新零售…

二叉树的非递归遍历(c++)

前序 . - 力扣&#xff08;LeetCode&#xff09;. - 备战技术面试&#xff1f;力扣提供海量技术面试资源&#xff0c;帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/binary-tree-preorder-traversal/description/ 1---2---4---5--…

CentOS7 安装 Kamailio

https://www.kamailio.org/wiki/packages/rpms 官方文档说 yum -y install yum-utils yum-config-manager --add-repo https://rpm.kamailio.org/centos/kamailio.repo 但目前这样其实行不通 需要这样做&#xff1a; yum install --disablerepokamailio --enablerepokamai…

Web3Tools - 助记词生成

Web3Tools - 助记词生成工具 本文介绍了一个简单的助记词生成工具&#xff0c;使用 React 和 Material-UI 构建。用户可以选择助记词的语言和长度&#xff0c;然后生成随机的助记词并显示在页面上 功能介绍 选择语言和长度&#xff1a; 用户可以在下拉菜单中选择助记词的语言&…

收放卷伺服控制系统详细算法介绍(电子齿轮+张力PID卷绕轴控制功能块)

收放卷控制系统涉及的内容非常多,这里我们介绍全伺服系统利用电子齿轮指令实现主从轴的比例随动速度控制,收放卷控制算法介绍常用链接如下 1、收放卷+排线控制 收放卷+排线控制系统框图-CSDN博客文章浏览阅读24次。1、收放卷前馈量计算FC收放卷前馈量计算FC(CODESYS ST源代…

bevformer详解(1):论文介绍

3D 视觉感知任务,包括基于多摄像头的3D检测和地图分割对于自动驾驶系统至关重要。本文提出了一种名为BEVFormer的新框架,它通过使用空间和时间的Transformer 学习统一的BEV表示来支持多个自动驾驶感知任务。简而言之,BEVFormer通过预定义的网格形式的Bev Query与空间和时间空…

ssrf初步

一&#xff0c;简介 全称&#xff1a;Server-Side Request Forgery&#xff08;中文&#xff1a;服务器端请求伪造&#xff09; 攻击者从服务端发起请求&#xff0c;让服务器连接任意外部系统&#xff0c;从而泄露敏感数据。主要利用各种协议的请求伪造&#xff0c;例如php协…

TCP的四次挥手过程

TCP连接是双向传输的对等的模式&#xff08;全双工模式&#xff09;&#xff0c;就是说双方都可以同时向对方发送或接收数据。 而断开的时候&#xff0c;也是双方都可以主动断开&#xff0c;此时需要经过四次挥手的过程&#xff0c;流程如下图所示&#xff1a; 主动方发送FIN包…

面向侧扫声纳目标检测的YOLOX-ViT知识精馏

面向侧扫声纳目标检测的YOLOX-ViT知识精馏 摘要IntroductionRelated WorkYOLOv-ViTKnowledge DistillationExperimental Evaluation Knowledge Distillation in YOLOX-ViT for Side-Scan Sonar Object Detection 摘要 在本文中&#xff0c;作者提出了YOLOX-ViT这一新型目标检测…

大数据Scala教程从入门到精通第七篇:Scala在IDEA中编写Hello World

一&#xff1a;Scala在IDEA中编写Hello World 想让我们的idea支持scala的编写&#xff0c;需要安装一个插件。