FreeRtos列表和列表项

参考学习正点原子FreeRtos第七章
先对列表,列表项,迷你列表项介绍(这部分看书就行),其次是对列表项初始化等进行分析,配合实验进行理解

实验分析点这里
实验源码点这

列表

列表是FreeRTOS中的一个数据结构,概念上和链表有点类似,列表被用来跟踪FreeRTOS中的任务。与列表相关的全部东西都在文件 list.c和 list.h中。在list.h 中定义了一个叫List_t 的结构体,如下:

typedef struct xLIST
{
listFIRST_LIST_INTEGRITY_CHECK_VALUE					(1)
configLIST_VOLATILE UBaseType _t	uxNumberOfItems;	(2)
ListItem_t *configLIST_VOLATILE		pxIndex;			(3)
MiniListItem_t						xListEnd;			(4)
listSECOND_LIST_INTEGRITY_CHECK_VALUE					(5)
}List t;

在这里插入图片描述
在这里插入图片描述
重点关注示意图中几个成员,列表项和迷你列表项也是如此

列表项

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

struct xLIST_ITEM1
{
listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE									(1)
configLIST_VOLATILE Tick Type_t		xltemValue;								(2)
struct xLIST_ITEM 					* configLIST_VOLATILEpxNext;			(3)
struct xLIST_ITEM 					*configLIST_VOLATILE pxPrevious;		(4)
void 								*pvOwner;								(5)
void 								* configLIST_VOLATILE	pvContainer;	(6)
listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE									(7)
};
typedef struct xLIST_ITEM ListItem_t;

在这里插入图片描述

迷你列表项

上面我们我们说了列表项,现在来看一下迷你列表项,迷你列表项在文件 list.h中有定义,如下:

struct xMINI_LIST_ITEM
{
listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE								(1)
configLIST_VOLATILE TickType_t		xltem Value;						(2)
struct xLIST_ITEM 					* configLIST_VOLATILE pxNext;		(3)
struct xLIST_ITEM 					* configLIST_VOLATILE pxPrevious;	(4)
};
typedef struct xMINI_LIST_ITEM MiniListItem_t;

在这里插入图片描述

列表初始化

新创建或者定义的列表需要对其做初始化处理,列表的初始化其实就是初始化列表结构体List_t中的各个成员变量,列表的初始化通过使函数vListInitialise()来完成,此函数在list.c中有定义,函数如下:

void vListInitialise( List_t * const pxList )
{
	pxList->pxIndex = (Listltem_t * )&( pxList->xListEnd );				(1)
	pxList->xListEnd.xItemValue = portMAX_DELAY;						(2)
	pxList->xListEnd.pxNext= (Listltem_t* )&( pxList->xListEnd );		(3)
	pxList->xListEnd.pxPrevious = (ListItem_t* ) &(pxList->xListEnd );	(4)
	pxList->uxNumberOfltems = ( UBaseType_t ) OU;						(5)
	listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList );						(6)
	listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList );						(7)
}

pxList 就是要初始化的列表,那么来看看之前的示意图
这里把列表示意图看看
xListEnd 用来表示列表的末尾,上面也有介绍xListEnd 就是一个迷你列表项,看看迷你列表项的示意图
在这里插入图片描述
也就是说创建一个列表后,里面就已经包含了一个迷你列表项,列表pxIndex是用来索引列表项的,那么列表初始化函数中(1)意思,当前列表索引pxList->pxIndex指向就只有创建列表时迷你列表项的地址
(2)的意思书中有解释
在这里插入图片描述
(3)(4)就是将迷你列表项中的指针都指向xListEnd 地址
(5)就是将列表项的值初始化为0,很明显没有包含列表初始化时xListEnd (迷你列表项)
在这里插入图片描述

列表项初始化

同列表一样,列表项在使用的时候也需要初始化,列表项初始化由函数vListInitialiseltem()来完成,函数如下:

void vListInitialiseItem( ListItem_t * const pxItem )
{
	pxltem->pvContainer =NULL;	//初始化 pvContainer为 NULL

	//初始化用于完整性检查的变量,如果开启了这个功能的话。
	listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
	listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
};

列表初始化很简单,只是将列表项成员变量pvContainer初始化为NULL,并且给用于完整性检查的变量赋值。书中也有解释,列表项的成员变量比列表要多,怎么初始化函数就这么短?其他的成员变量什么时候初始化呢?这是因为列表项要根据实际使用情况来初始化,比如任务创建函数xTaskCreate()就会对任务堆栈中的xStateListltem和xEventListItem这两个列表项中的其他成员变量在做初始化,任务创建过程后面会详细讲解。

列表项插入

函数vListInsert()的参数pxList决定了列表项要插入到哪个列表中,pxNewListItem决定了要插入的列表项,但是这个列表项具体插入到什么地方呢?要插入的位置由列表项中成员变量xItemValue来决定。列表项的插入根据xItemValue 的值按照升序的方式排列!接下来我们来具体看一下函数vListInsert()的整个运行过程,函数代码如下:

//pxList:		列表项要插入的列表
//pxNewListItem :	要插入的列表项
void vListInsert( List_t *const pxList, ListItem_t *const pxNewListItem )
{
	Listltem_t *pxIterator;
	const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;	(1)
	listTEST_LIST_INTEGRITY( pxList );									(2)
	listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );
	if( xValueOfInsertion == portMAX_DELAY )							(3)
	{
		pxIterator = pxList->xListEnd.pxPrevious;						(4)
	}
	else
	{
		for( pxIterator = ( ListItem_t * )&( pxList->xListEnd ); pxIterator->\(5)
				pxNext->xItemValue <=xValueOfInsertion; pxIterator = pxIterator->pxNext )
					{
						//空循环,什么也不做!
					}
	}
	pxNewListItem->pxNext = pxIterator->pxNext;			(6)
	pxNewListItem->pxNext->pxPrevious = pxNewListItem;
	pxNewListItem->pxPrevious = pxIterator;
	pxlterator->pxNext = pxNewListItem;
	pxNewListltem->pvContainer = ( void * ) pxList;		(7)
	(pxList->uxNumberOfltems)++;						(8)
}

先看列表项示意图
在这里插入图片描述
先看(1)xValueOfInsertion 中保存的是要插入列表项的列表项值
在这里插入图片描述
(3)xValueOfInsertion 的值如果等于portMAX_DELAY ,那么就是在列表的最末尾进行插入,因为列表初始化时的xListEnd 的xItemValue 值为portMAX_DELAY
(4)pxIterator 是一个列表项指针,如果是在最末尾插入那么pxIterator 就指向要插入列表的迷你列表项的列表项值的地址,也就是下图中的位置
在这里插入图片描述
(5)如果不是末尾也就是代码中else代码那么就还是从列表的迷你列表项地址开始遍历(上图箭头指向位置),

pxIterator = ( ListItem_t * )&( pxList->xListEnd );

假如现在列表里面有两个列表项,遍历的条件就是下一个列表项的列表项值与要插入的列表项的列表项值进行比较,

pxIterator->pxNext->xItemValue <=xValueOfInsertion;

也就是下图指向的值与要插入的值进行比较
在这里插入图片描述
如果要插入项的项值比上图中的值小或等于上图中的值,那么

pxIterator = pxIterator->pxNext

pxIterator 指针就指向上图中的位置
依次循环
(6)的代码就是将要插入项中的指针指向进行改变,对着代码看下图
在这里插入图片描述
(7)是指定列表项的列表,(8)是插入完成后列表的列表项个数加1。
后面的尾插入、删除思路分析方法与此类似

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值