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.hqwc.cn/news/691589.html

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

相关文章

【MySQL】基本操作

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;折纸花满衣 &#x1f3e0;个人专栏&#xff1a;MySQL 目录 &#x1f449;&#x1f3fb;创建和删除数据库&#x1f449;&#x1f3fb;数据库编码集和数据库校验集校验规则对数据库的影响 &#x1f449;&…

泰迪智能科技大数据开发实训平台功能介绍

大数据开发实训平台是面向实训课和课后训练的编程实训平台&#xff0c;平台底层基于Docker技术&#xff0c;采用容器云部署方案&#xff0c;预装大数据相关课程教学所需的实训环境&#xff0c;拥有1主2从的Hadoop集群&#xff0c;还能够自主定制环境&#xff0c;并能够与实训管…

SSM【Spring SpringMVC Mybatis】—— Spring(一)

目录 1、初识Spring 1.1 Spring简介 1.2 搭建Spring框架步骤 1.3 Spring特性 1.5 bean标签详解 2、SpringIOC底层实现 2.1 BeanFactory与ApplicationContexet 2.2 图解IOC类的结构 3、Spring依赖注入数值问题【重点】 3.1 字面量数值 3.2 CDATA区 3.3 外部已声明be…

JeeSite V5.7.0 发布,Java快速开发平台,Vite5、多项重构重磅升级

JeeSite V5.7.0 发布&#xff0c;Java快速开发平台&#xff0c;Vite5、多项重构重磅升级 升级内容 新增 参数配置 IP 地址黑白名单过滤器动态参数 新增 侧边栏是否展开第一个菜单的开关 first-open 新增 AesTypeHandler 处理字段数据加密解密或脱敏 新增 JsonTypeHandler …

PCIE协议-2-事务层规范-Message Request Rules

2.2.8 消息请求规则 本文档定义了以下几组消息&#xff1a; INTx 中断信号电源管理错误信号锁定事务支持插槽电源限制支持厂商定义消息延迟容忍度报告&#xff08;LTR&#xff09;消息优化缓冲区冲洗/填充&#xff08;OBFF&#xff09;消息设备就绪状态&#xff08;DRS&#…

机器人系统ros2-开发实践06-将静态坐标系广播到 tf2(Python)-定义机器人底座与其传感器或非移动部件之间的关系

发布静态变换对于定义机器人底座与其传感器或非移动部件之间的关系非常有用。例如&#xff0c;最容易推断激光扫描仪中心框架中的激光扫描测量结果。 1. 创建包 首先&#xff0c;我们将创建一个用于本教程和后续教程的包。调用的包learning_tf2_py将依赖于geometry_msgs、pyth…

EasyRecovery(易恢复) 使用测试及详细使用方法

你有没有因为数据丢失懊悔不已&#xff0c;EasyRecovery&#xff08;易恢复&#xff09;&#xff0c;来自美国拥有38年数据恢复的软件&#xff0c;只有收费版&#xff0c;重要事情说三遍&#xff0c;EasyRecovery 没有免费版&#xff0c;可以成功找回删除的部分文件&#xff0c…

璩静霸道言论引发百度风波随笔

从5月9日晚开始有关“百度副总裁璩静已从公司离职”的消息&#xff0c;仅两天时间就几乎布满互联网所有知名自媒体平台&#xff0c;可谓兹事体大&#xff0c;无异于互联网发生了一场八级地震&#xff0c;波及面之广&#xff0c;匪夷所思&#xff01; 百度截图 尽管笔者一直密切…

A Dexterous Hand-Arm Teleoperation System

A Dexterous Hand-Arm Teleoperation System Based on Hand Pose Estimation and Active Vision解读 摘要1. 简介2.相关工作2.1 机器人遥操作2.2 主动视觉&#xff08;Active Vision&#xff09; 3. 硬件设置4. 基于视觉的机器人手部姿态估计4.1 Transteleop4.2 Dataset 5. 主动…

【图解计算机网络】TCP 重传、滑动窗口、流量控制、拥塞控制

TCP 重传、滑动窗口、流量控制、拥塞控制 TCP 重传超时重传快速重传 滑动窗口流量控制拥塞控制慢启动拥塞避免拥塞发生快速恢复 TCP 重传 TCP重传是当发送的报文发生丢失的时候&#xff0c;重新发送丢失报文的一种机制&#xff0c;它是保证TCP协议可靠性的一种机制。 TCP重传…

AJ65SBT2B-64DA 三菱CC-Link D/A转换模块

AJ65SBT2B-64DA 是将数字值(16位有符号BIN数据)转换为模拟值(电压或电流)的模块。 AJ65SBT2B-64DA参数说明&#xff1a;4通道&#xff1b;输入分辨率0~12000&#xff0c;-12000~12000&#xff0c;-16000~16000&#xff1b;输出DC-10~10V&#xff0c;DC0~20mA&#xff1b;转换速…

掌握未来搜索的钥匙:深入解析 Milvus 向量搜索引擎的终极指南!

在大数据时代&#xff0c;向量搜索技术愈发重要。作为一个开源的向量相似性搜索引擎&#xff0c;Milvus 提供了基于向量的相似性搜索功能&#xff0c;广泛应用于机器学习、人工智能等领域。本文将深入介绍 Milvus 的基本概念&#xff0c;包括其介绍、主要作用、使用方法及注意事…