第八章 FreeRTOS的列表与列表项

本文详细介绍了FreeRTOS中列表、列表项的结构,包括其特点和组成部分,以及相关API函数如初始化、插入和删除操作。主要关注vListInitialise(),vListInitialiseItem(),vListInsert(),vListInsertEnd(),和uxListRemove()的用法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一.列表与列表项的简介

1.1 列表结构体成员介绍

1.2 列表项结构体成员介绍

1.3 迷你列表项结构体成员介绍

二.相关API函数的介绍

2.1列表初始化vListInitialise()

2.2列表项初始化vListInitialiseItem()

2.3列表项升序插入vListInsert()

2.4列表项末尾插入vListInsertEnd()

2.5删除列表项函数uxListRemove()


一.列表与列表项的简介

列表:是 FreeRTOS 中的一个数据结构,概念上和链表有点类似,列表被用来跟踪 FreeRTOS中的任务。列表有阻塞、就绪、挂起列表等,这些列表用来表示任务的状态。


列表项:存放在列表中的项目。列表项类似于链表的节点,列表项可以理解为存放数据的,一个数据的下一个next或者上一个prev指向谁,还有是一个数据代表哪一个任务。

列表相当于链表,列表项相当于节点,FreeRTOS 中的列表是一个双向环形链表。

列表的特点

        列表项间的地址是非连续的(地址连不连续无所谓,和数组有区别,数组是连续的地址),是人为的连接到一起的。列表项的数目是由后期添加的个数决定的,随时可以改变

数组的特点:

        数组成员地址是连续的,数组在最初确定了成员数量后期无法改变。

在OS中任务的数量是不确定的,并且任务状态是会发生改变的,所以非常适合用列表这种数据结构。

有关于列表的东西均在文件 list.c 和 list.h 中(属于FreeRTOS的源码)

1.1 列表结构体成员介绍

typedef struct xLIST
{
    	listFIRST_LIST_INTEGRITY_CHECK_VALUE			/* 校验值 */
    	volatile UBaseType_t uxNumberOfItems;			/* 列表中的列表项数量 */
   	    ListItem_t * configLIST_VOLATILE pxIndex		/* 用于遍历列表项的指针 */
    	MiniListItem_t xListEnd					        /* 末尾列表项 */
    	listSECOND_LIST_INTEGRITY_CHECK_VALUE		    /* 校验值 */
} List_t;

1、在该结构体中, 包含了两个宏,这两个宏是确定的已知常量, FreeRTOS通过检查这两个常量的值, 来判断列表的数据在程序运行过程中,是否遭到破坏 ,该功能一般用于调试, 默认是不开启的(没有用到);

2、成员uxNumberOfItems用于记录列表中列表项的个数不包含末尾列表项xListEnd);

3、成员pxIndex于指向列表中的某个列表项,一般用于遍历列表中的所有列表项;

4、成员xListEnd一个迷你列表项,总是排在最末尾;

1.2 列表项结构体成员介绍

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							                /* 列表项的拥有者 */
    	struct    xLIST * configLIST_VOLATILE pxContainer; 		/* 列表项所在列表 */
   	    listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE			    /* 用于检测列表项的数据完整性 */
};
typedef struct xLIST_ITEM ListItem_t; 	

 首末两项可以不用看,用于检测数据完整性,并没有使用此功能。

1、成员xItemValue 列表项的值,这个值多用于按升序对列表中的列表项进行排序

2、成员pxNext 和 pxPrevious 分别用于指向列表中列表项的下一个列表项和上一个列表项

3、成员pxOwner 用于指向包含列表项的对象通常是任务控制块,指向某一个任务);

4、成员pxContainer 用于指向列表项所在列表就绪、阻塞、挂起,指向某一个状态)。

1.3 迷你列表项结构体成员介绍

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、成员xItemValue 列表项的值这个值多用于按升序对列表中的列表项进行排序

2、成员pxNext 和 pxPrevious 分别用于指向列表中列表项的下一个列表项和上一个列表项

3、迷你列表项只用于标记列表的末尾(迷你列表项永远排在列表末尾)挂载其他插入列表中的列表项(当列表中没有其他列表项时,新插入的列表项和迷你列表项互相指向)

因此不需要成员变量 pxOwner 和 pxContainer,以节省内存开销。

二.相关API函数的介绍

函数

描述

vListInitialise()

初始化列表(列表的初始状态通过此函数得到)

vListInitialiseItem()

初始化列表项(初始化,是对列表、列表项结构体中的变量赋一个初始值)

vListInsertEnd()

列表末尾插入列表项

vListInsert()

列表插入列表项(升序插入,根据列表项的数值xItemValue进行列表升序插入)

uxListRemove()

列表移除列表项

2.1列表初始化vListInitialise()

void vListInitialise(List_t * const pxList)
{	
    /*  初始化时,列表中只有 xListEnd,因此 pxIndex 指向 xListEnd */
	pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd );
    /* xListEnd 的值初始化为最大值,用于列表项升序排序时,排在最后 */
	pxList->xListEnd.xItemValue = portMAX_DELAY;
    /* 初始化时,列表中只有 xListEnd,因此上一个和下一个列表项都为 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 );
} 

参数介绍

pxList:待初始化列表

2.2列表项初始化vListInitialiseItem()

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

参数介绍

pxItem:待初始化列表项

pxContainer参数表示列表项所属于哪一个列表,初始化列表项时是不属于任何列表的,所以设置为空。

2.3列表项升序插入vListInsert()

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; 				        /* 插入的位置为列表 xListEnd 前面 */ 
	} 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->pxContainer = pxList; 						        /* 更新待插入列表项所在列表 */ 
	( pxList->uxNumberOfItems )++;							            /* 更新列表中列表项的数量 */ 
}

参数介绍

pxList :要插入的目标列表;

pxNewListItem:待插入的列表项,将列表项插入到目标列表中,并且按列表项的值进行升序排列;

此函数用于将待插入列表的列表项按照列表项值升序进行排序,有序地插入到列表中。在插入过程中,如果列表项的值等于末尾列表项的值,则插入到末尾列表项前面; 否则遍历列表,找到要插入的位置。

2.4列表项末尾插入vListInsertEnd()

void vListInsertEnd (  List_t * const pxList ,   ListItem_t * const pxNewListItem  )
{
	 省略部分非关键代码 … …
	/* 获取列表 pxIndex 指向的列表项 */	
    ListItem_t * const pxIndex = pxList->pxIndex;
	/* 更新待插入列表项的指针成员变量 */
	pxNewListItem->pxNext = pxIndex;
	pxNewListItem->pxPrevious = pxIndex->pxPrevious;
 	/* 更新列表中原本列表项的指针成员变量 */
	pxIndex->pxPrevious->pxNext = pxNewListItem;
	pxIndex->pxPrevious = pxNewListItem;
	/* 更新待插入列表项的所在列表成员变量 */	pxNewListItem->pxContainer = pxList;
	/* 更新列表中列表项的数量 */
	( pxList->uxNumberOfItems )++;
} 

参数介绍:

pxList :要插入的目标列表;

pxNewListItem :待插入的列表项,将列表项插入到目标列表中;

此函数并不是真正的将待插入的列表项插入到目标列表末尾而是根据pxIndex指针,将待插入的列表项插入到pxIndex指针指向的列表项的前一个位置,是一种无序的插入方法

2.5删除列表项函数uxListRemove()

UBaseType_t  uxListRemove (   ListItem_t *  const    pxItemToRemove ) 
{
    /* 获取待删除列表项所属列表 */
	List_t * const pxList = pxItemToRemove->pxContainer; 
    /* 从列表中移除列表项 */
	pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;
	pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext; 	
    /*如果 pxIndex 正指向待移除的列表项 */
	if( pxList->pxIndex == pxItemToRemove ) 
	{
        /*pxIndex 指向上一个列表项*/ 
	 	pxList->pxIndex = pxItemToRemove->pxPrevious;
	} else 
	{ 
		mtCOVERAGE_TEST_MARKER(); 
	} 
    /*将待移除的列表项的所在列表指针清空*/ 
	pxItemToRemove->pxContainer = NULL; 
    /*更新列表中列表项的数量*/ 
	( pxList->uxNumberOfItems )--; 
    /*返回移除后的列表中列表项的数量*/ 
	return pxList->uxNumberOfItems; 
}

参数介绍:

pxItemToRemove:待移除的列表项(列表项结构体成员中pxContainer用于表示属于哪一个列表,所以入口参数只有一个,不需要所在列表);

UBaseType_t整数返回值:待移除列表项移除后,所在列表剩余列表项的数量。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值