FreeRTOS链表

1、 链表介绍

1.1 链表定义

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.2 FreeRTOS 中链表的实现

1.2.1 链表节点数据结构

 struct xLIST_ITEM
 {
	 TickType_t xItemValue; /* 辅助值,用于帮助节点做顺序排列 */ (1)
	 struct xLIST_ITEM * pxNext; /* 指向链表下一个节点 */ (2)
	 struct xLIST_ITEM * pxPrevious; /* 指向链表前一个节点 */ (3)
	 void * pvOwner; /* 指向拥有该节点的内核对象,通常是 TCB */(4)
	 void * pvContainer; /* 指向该节点所在的链表 */ (5)
 };
 typedef struct xLIST_ITEM ListItem_t; /* 节点数据类型重定义 */ (6)

链表根节点数据结构体

typedef struct xLIST
{
	UBaseType_t uxNumberOfItems; /* 用于表示该链表下有多少个节点,根节点除外 */ (1)
	ListItem_t * pxIndex; /* 链表节点索引指针 链表节点索引指针, 用于遍历节点*/ (2)
	MiniListItem_t xListEnd; /* 链表最后一个节点 */ (3)
} List_t;

链表精简节点结构体

struct xMINI_LIST_ITEM
{
	TickType_t xItemValue; /* 辅助值,用于帮助节点做升序排列 */
	struct xLIST_ITEM * pxNext; /* 指向链表下一个节点 */
	struct xLIST_ITEM * pxPrevious; /* 指向链表前一个节点 */
};
typedef struct xMINI_LIST_ITEM MiniListItem_t; /* 精简节点数据类型重定义 */

在这里插入图片描述

1.2.2 链表数据定义

portmacro.h
/* 数据类型重定义 */
#define portCHAR		char
#define portFLOAT		float
#define portDOUBLE		double
#define portLONG		long
#define portSHORT		short
#define portSTACK_TYPE	uint32_t
#define portBASE_TYPE	long

typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t;
typedef unsigned long UBaseType_t;

#if( configUSE_16_BIT_TICKS == 1 )
	typedef uint16_t TickType_t;
	#define portMAX_DELAY ( TickType_t ) 0xffff
#else
	typedef uint32_t TickType_t;
	#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif

1.2.3 链表节点初始化

void vListInitialiseItem( ListItem_t * const pxItem )
{
	/* 初始化该节点所在的链表为空,表示节点还没有插入任何链表 */
	pxItem->pvContainer = NULL; (1)
}

1.2.4 链表根节点初始化

/* 链表根节点初始化 */
void vListInitialise( List_t * const pxList )
{
	/* 将链表索引指针指向最后一个节点 即第一个节点, 或者第零个
	 节点更准确,因为这个节点不会算入节点计数器的值。*/
	pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd );

	/* 将链表最后一个节点的辅助排序的值设置为最大,确保该节点就是链表的最后节点 
	将链表最后(也可以理解为第一) 一个节点的辅助排序的值设置为最大,确保该节点就是链
	表的最后节点(也可以理解为第一)。
	*/
	pxList->xListEnd.xItemValue = portMAX_DELAY;

    /* 将最后一个节点的pxNext和pxPrevious指针均指向节点自身,表示链表为空 将最后一个节点
    (也可以理解为第一) 的 pxNext 和 pxPrevious 指针均指向节点自身,表示链表为空。*/
	pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd );
	pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );

	/* 初始化链表节点计数器的值为0,表示链表为空 */
	pxList->uxNumberOfItems = ( UBaseType_t ) 0U;
}

在这里插入图片描述

1.3 FreeRTOS 中链表的操作

1.3.1 节点插入到链表的尾部

/* 将节点插入到链表的尾部 */
void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem )
{
	ListItem_t * const pxIndex = pxList->pxIndex;

	pxNewListItem->pxNext = pxIndex;   					//1
	pxNewListItem->pxPrevious = pxIndex->pxPrevious;    //2
	pxIndex->pxPrevious->pxNext = pxNewListItem;        //3
	pxIndex->pxPrevious = pxNewListItem;                //4

	/* 记住该节点所在的链表 */
	pxNewListItem->pvContainer = ( void * ) pxList;  	//5

	/* 链表节点计数器++ */
	( pxList->uxNumberOfItems )++;                  	//6
}

在这里插入图片描述

1.3.2 节点按照升序排列插入到链表

void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem )
{
	ListItem_t *pxIterator;
	
	/* 获取节点的排序辅助值 */
	const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;			(1)

	/* 寻找节点要插入的位置 */												(2)
	if( xValueOfInsertion == portMAX_DELAY )
	{
		pxIterator = pxList->xListEnd.pxPrevious;
	}
	else
	{
		for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd );
		     pxIterator->pxNext->xItemValue <= xValueOfInsertion; 
			 pxIterator = pxIterator->pxNext )
		{
			/* 没有事情可做,不断迭代只为了找到节点要插入的位置 */			
		}
	}
	/* 根据升序排列,将节点插入 */ 											(3)
	pxNewListItem->pxNext = pxIterator->pxNext;						//1
	pxNewListItem->pxNext->pxPrevious = pxNewListItem;				//2
	pxNewListItem->pxPrevious = pxIterator;							//3
	pxIterator->pxNext = pxNewListItem;								//4

	/* 记住该节点所在的链表 */
	pxNewListItem->pvContainer = ( void * ) pxList;					//5

	/* 链表节点计数器++ */
	( pxList->uxNumberOfItems )++;									//6
}

在这里插入图片描述

1.3.3 节点从链表删除

/* 将节点从链表中删除 */
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
{
	/* 获取节点所在的链表 */
	List_t * const pxList = ( List_t * ) pxItemToRemove->pvContainer;

	pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;
	pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;

	/* Make sure the index is left pointing to a valid item. */
	if( pxList->pxIndex == pxItemToRemove )
	{
		pxList->pxIndex = pxItemToRemove->pxPrevious;
	}

	/* 初始化该节点所在的链表为空,表示节点还没有插入任何链表 */
	pxItemToRemove->pvContainer = NULL;
	
	/* 链表节点计数器-- */
	( pxList->uxNumberOfItems )--;

	/* 返回链表中剩余节点的个数 */
	return pxList->uxNumberOfItems;
}

在这里插入图片描述

1.3.4 节点带参宏小函数

/*
************************************************************************
*                                宏定义
************************************************************************
*/
/* 初始化节点的拥有者 */
#define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner )		( ( pxListItem )->pvOwner = ( void * ) ( pxOwner ) )
/* 获取节点拥有者 */
#define listGET_LIST_ITEM_OWNER( pxListItem )	( ( pxListItem )->pvOwner )

/* 初始化节点排序辅助值 */
#define listSET_LIST_ITEM_VALUE( pxListItem, xValue )	( ( pxListItem )->xItemValue = ( xValue ) )

/* 获取节点排序辅助值 */
#define listGET_LIST_ITEM_VALUE( pxListItem )	( ( pxListItem )->xItemValue )

/* 获取链表根节点的节点计数器的值 */
#define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList )	( ( ( pxList )->xListEnd ).pxNext->xItemValue )

/* 获取链表的入口节点 */
#define listGET_HEAD_ENTRY( pxList )	( ( ( pxList )->xListEnd ).pxNext )

/* 获取链表的第一个节点 */
#define listGET_NEXT( pxListItem )	( ( pxListItem )->pxNext )

/* 获取链表的最后一个节点 */
#define listGET_END_MARKER( pxList )	( ( ListItem_t const * ) ( &( ( pxList )->xListEnd ) ) )

/* 判断链表是否为空 */
#define listLIST_IS_EMPTY( pxList )	( ( BaseType_t ) ( ( pxList )->uxNumberOfItems == ( UBaseType_t ) 0 ) )

/* 获取链表的节点数 */
#define listCURRENT_LIST_LENGTH( pxList )	( ( pxList )->uxNumberOfItems )

/* 获取链表节点的OWNER,即TCB */
#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList )										\
{																							\
	List_t * const pxConstList = ( pxList );											    \
	/* 节点索引指向链表第一个节点调整节点索引指针,指向下一个节点,
    如果当前链表有N个节点,当第N次调用该函数时,pxInedex则指向第N个节点 */\
	( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext;							\
	/* 当前链表为空 */                                                                       \
	if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) )	\
	{																						\
		( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext;						\
	}																						\
	/* 获取节点的OWNER,即TCB */                                                             \
	( pxTCB ) = ( pxConstList )->pxIndex->pvOwner;											 \
}

#define listGET_OWNER_OF_HEAD_ENTRY( pxList )  ( (&( ( pxList )->xListEnd ))->pxNext->pvOwner )

1.4 完结撒花~~~~~~

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值