FreeRTOS数据结构--链表和链表项

Posted -阿威-

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FreeRTOS数据结构--链表和链表项相关的知识,希望对你有一定的参考价值。

结构体定义

/*链表结构体*/
typedef struct xLIST
{
	listFIRST_LIST_INTEGRITY_CHECK_VALUE  /*用于链表完整性检查*/
	configLIST_VOLATILE UBaseType_t uxNumberOfItems; /*记录链表项数目*/
	ListItem_t * configLIST_VOLATILE pxIndex; /*用于遍历链表,初始化会指向最后的链表项,这里需要注意使用了volatile关键字,表明该指针可能会在其他地方修改*/
	MiniListItem_t xListEnd;/*用于标记链表尾*/
	listSECOND_LIST_INTEGRITY_CHECK_VALUE /*用于链表完整性检查*/
} List_t;
/*链表项结构体*/
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 /*用于链表完整性检查*/	
};
/*迷你链表项结构体*/
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;
};

根据定义可以看出以下几点:

  1. 链表结构是一个双向链表。
  2. 每个链表都由链表和链表项组成。
  3. 链表结构体本身有一个迷你链表项,用来标记链表的结尾。

链表和链表项初始化

/*链表初始化*/
void vListInitialise( List_t * const pxList )
{
	/*将链表的Index索引指针指向自身的迷你链表项,即链表结尾*/
	pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd );			
	/*将迷你链表项值设置为最大值,确保处于链表结尾*/
	pxList->xListEnd.xItemValue = portMAX_DELAY;
	/*由于链表中没有节点,链表尾节点的下一项和上一项都是自身,表明这是一个循环链表*/
	pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd );
	pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );
	pxList->uxNumberOfItems = ( UBaseType_t ) 0U;
	/*初始化链表的完整性检查值*/
	listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList );
	listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList );
}
/*链表项初始化*/
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 );
}

链表的操作

链表的插入会根据List Item Value进行升序排列,其他并没有什么特殊的地方。初始化并插入两个节点后大概的数据结构,如下图所示:
链表

从图中可以看出,List初始化并添加节点后,List Item 1/List Item 2 和 List自己的xListEnd节点一起组成了一个双向循环的链表。

Q&A

1).如何完成链表的完整性检查?
如果打开了完整性检查的开关(configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES),每个链表和链表项结构都会定义listFIRST_LIST_INTEGRITY_CHECK_VALUElistSECOND_LIST_INTEGRITY_CHECK_VALUE(mini链表项没有定义这个),该定义是一个16位或32位的整形数,在链表或链表项初始化的时候会将该变量初始化为0x5a5a或0x5a5a5a5a,在检查的时候如果这两个变量都没有改变则通过完整性检查,否则认为链表被破坏。

2).如何使用List?

  1. 必须先定义一个List_t的全局变量,比如Timer中的 xActiveTimerList1
  2. 每一个节点结构体必须包含xLIST_ITEM类型的成员。
  3. 初始化链表后,将含有List Item成员的数据结构按照链表项值的大小插入到链表中,比如Timer中利用该值溢出的判断。
  4. 设置好pvOwner指针,后续可以根据该指针反向找到该节点的具体结构,如Timer_t。

以上是关于FreeRTOS数据结构--链表和链表项的主要内容,如果未能解决你的问题,请参考以下文章

线性表——顺序表和链表

C中线性表和链表的区别

FreeRTOSFreeRTOS学习笔记— 手写FreeRTOS双向链表/源码分析

链表是顺序表吗?

顺序表和链表的模板

哈希表和链表的 C++ 访问冲突