FreeRTOS中的链表实现(学习笔记)

本文章参考野火的“[野火®]《FreeRTOS 内核实现与应用开发实战—基于STM32》”,特此申明。

在学习链表之前,先介绍一下freertos的数据类型,在freertos原码中对标准C的数据类型进行了重定义上一张已经介绍过freeRTOS的类型重定义

在FreeRTOS中链表的结构体有三种:

第一种:普通节点的结构体,结构体成员包含:

        辅助值:用来帮助节点做顺序排序的,最大值为0xffff或0xffff ffff,由configUSE_16_BIT_TICKS宏决定。

        指向上一个节点和下一个节点的两个指针,类似于普通的双向循链表的操作。

        pvOwner:指向拥有该节点的内核对象(暂时不知道有何用处)。

        pvContainer:指向该节点所在的链表(链表的根节点)。

/*定义普通节点结构体*/
typedef struct xLIST_ITEM
{
	TickType_t xItemValue;					/*辅助值,用于帮助节点做顺序排列*/
	struct xLIST_ITEM *pxNext;		        /*指向链表下一个节点*/
	struct xLIST_ITEM *pxPrevious;	        /*指向链表上一个节点*/
	void *pvOwner;							/*指向拥有该节点的内核对象,通常是 TCB */
	void *pvContainer; 						/*指向该节点所在的链表 */ 
}ListItem_t;

第二种:定义最后一个链表节点的结构体

/*定义最后一个链表节点的结构体*/
typedef struct xMINI_LIST_ITEM
{
	TickType_t xItemValue;                  /*辅助值,用于帮助节点做升序排列 */
	struct xLIST_ITEM *  pxNext;            /*指向链表下一个节点 */
	struct xLIST_ITEM *  pxPrevious;        /*指向链表前一个节点 */ 
}MiniListItem_t; 

第三种:定义根节点结构体

/*定义根节点结构体*/
typedef struct xLIST
{
	UBaseType_t uxNumberOfItems;			/*链表节点计数器,节点总数*/
	ListItem_t  *pxIndex;					/*链表节点索引指针*/
	MiniListItem_t xListEnd;				/*链表最后一个节点*/
}List_t;

对链表的初始化

/*链表根节点初始化*/
void vListInitialise( List_t * const pxList )
{
	/*将链表索引指针指向最后一个节点*/
	pxList->pxIndex = (ListItem_t  *)&pxList->xListEnd;
	/*设置链表最后一个节点的辅助排序值为最大*/
	pxList->xListEnd.xItemValue = portMAX_DELAY;
	/*设置链表最后一个节点的前一个和后一个节点指向本身,说明该链表为空*/
	pxList->xListEnd.pxPrevious = (ListItem_t  *)&pxList->xListEnd;
	pxList->xListEnd.pxNext = (ListItem_t  *)&pxList->xListEnd;
	/*设置链表节点数为0*/
	pxList->uxNumberOfItems = (UBaseType_t) 0U;
}

/*普通节点初始化*/
void vListInitialiseItem( ListItem_t * const pxItem )
{
	/*初始化链表所在节点为空,表示未插入任何链表*/
	pxItem->pvContainer = NULL;
}

对链表的增删改查

/*把节点插入到链表的尾部*/
void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem )
{
	/*定义一个节点指向链表的索引,即最后一个节点*/
	ListItem_t * const pxIndex = pxList->pxIndex;

	/*新节点的下一个指向索引,即尾部*/
	pxNewListItem->pxNext = pxIndex;
	/*新节点的上一个指向索引的上一个*/
	pxNewListItem->pxPrevious = pxIndex->pxPrevious;
	/*索引的上一个的下一个重新指向新插入的节点,原指向索引*/
	pxIndex->pxPrevious->pxNext = pxNewListItem;
	/*索引的上一个指向新节点*/
	pxIndex->pxPrevious = pxNewListItem;

	/*新节点所在的链表指向该链表*/
	pxNewListItem->pvContainer = ( void * ) pxList;

	/*该链表的节点数加1*/
	( pxList->uxNumberOfItems )++;
}

/*把该节点按升序插入*/
void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem )
{
	ListItem_t *pxIterator;
	
	/*定义一个不可改变的变量存放该节点的辅助值*/
	const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;

	
	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;

	( pxList->uxNumberOfItems )++;
}

/*删除节点*/
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;

	/*如果删除的时索引则将索引变成上一个*/
	if( pxList->pxIndex == pxItemToRemove )
	{
		pxList->pxIndex = pxItemToRemove->pxPrevious;
	}


	pxItemToRemove->pvContainer = NULL;
	
	( pxList->uxNumberOfItems )--;

	return pxList->uxNumberOfItems;
}

验证

#include "list.h"

struct xLIST       List_Test1;
struct xLIST       List_Test2;


struct xLIST_ITEM  List_Item1;
struct xLIST_ITEM  List_Item2;
struct xLIST_ITEM  List_Item3;
struct xLIST_ITEM  List_Item4;

int main()
{
    vListInitialise( &List_Test1 );
		vListInitialise( &List_Test2 );
    
    vListInitialiseItem( &List_Item1 );
    List_Item1.xItemValue = 1;
       
    vListInitialiseItem( &List_Item2 );
    List_Item2.xItemValue = 2;
    
    vListInitialiseItem( &List_Item3 );
    List_Item3.xItemValue = 3;
	
	    vListInitialiseItem( &List_Item4 );
    List_Item4.xItemValue = 4;

    
  
    vListInsert( &List_Test1, &List_Item2 );    
    vListInsert( &List_Test1, &List_Item1 );
    vListInsert( &List_Test1, &List_Item3 ); 

		vListInsert( &List_Test2, &List_Item4 );
    
    for(;;)
	{
		
	}

}



软件仿真

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值