汽车交易网站系统建设,毕业设计难度适中的网站开发项目题目,莆田有建设网站的公司码,注册网站做网销写在前面
本文主要是对于 FreeRTOS 中链表相关内容的详细解释#xff0c;代码大部分参考了野火FreeRTOS教程配套源码#xff0c;作了一小部分修改。
一、结构体定义
主要包含三种结构体#xff1a;
普通节点结构体结尾节点#xff08;mini节点#xff09;结构体链表结…写在前面
本文主要是对于 FreeRTOS 中链表相关内容的详细解释代码大部分参考了野火FreeRTOS教程配套源码作了一小部分修改。
一、结构体定义
主要包含三种结构体
普通节点结构体结尾节点mini节点结构体链表结构体
1.普通节点结构体
一个完整的节点包含五个参数
节点的序号用于确定节点在链表中的位置前指针指向本节点的前一个节点后指针指向本节点的下一个节点本节点所属的内核对象通常是TCBTask Control Block是FreeRTOS中用于管理任务的数据结构。该节点所属的链表
结构体定义如下
/* 节点结构体定义 */
struct xLIST_ITEM
{TickType_t xItemValue; /* 辅助值用于帮助节点做顺序排列 */ struct xLIST_ITEM * pxNext; /* 指向链表下一个节点 */ struct xLIST_ITEM * pxPrevious; /* 指向链表前一个节点 */ void * pvOwner; /* 指向拥有该节点的内核对象通常是TCB */void * pvContainer; /* 指向该节点所在的链表 */
};
typedef struct xLIST_ITEM ListItem_t; /* 节点数据类型重定义 */
2.结尾节点mini节点结构体
Mini节点没有所属内核和所属链表信息主要被用作双向列表的结尾只有三种信息
节点序号值标识节点在链表中的位置前指针后指针
结构体定义如下
/* mini节点结构体定义作为双向链表的结尾因为双向链表是首尾相连的头即是尾尾即是头 */
struct xMINI_LIST_ITEM
{TickType_t xItemValue; /* 辅助值用于帮助节点做升序排列 */struct xLIST_ITEM * pxNext; /* 指向链表下一个节点 */struct xLIST_ITEM * pxPrevious; /* 指向链表前一个节点 */
};
typedef struct xMINI_LIST_ITEM MiniListItem_t; /* 最小节点数据类型重定义 */3.链表结构体
链表需要三种参数
链表节点计数器统计链表中的节点总数链表节点索引指针指向链表中目前要操作的节点链表最后一个节点的指针
结构体定义如下
/* 链表结构体定义 */
typedef struct xLIST
{UBaseType_t uxNumberOfItems; /* 链表节点计数器 */ListItem_t * pxIndex; /* 链表节点索引指针 */MiniListItem_t xListEnd; /* 链表最后一个节点 */
} List_t;二、链表基本函数定义
主要包括下面几种函数
节点初始化函数空链表初始化函数将新节点插入到链表尾部的函数将新节点按升序插入链表的函数从链表中删除节点的函数
1.节点初始化函数
传入要初始化的节点将该节点的所属链表参数设置为空即可。
函数定义如下
//节点初始化
void vListInitialiseItem(ListItem_t * const pxItem)
{pxItem-pvContainer NULL; //将该节点所在链表初始化为空表示该节点还没有插入任何链表
}2. 空链表初始化函数
需要的步骤如下
将指针索引指向最后一个节点最后一个节点的排序值设置为最大取决于portmacro中portMAX_DELAY宏定义最后一个节点的前后指针都指向节点自身链表节点计数器设置为 0
代码如下
//空链表初始化
void vListInitialise(List_t * const pxList)
{//指针索引指向最后一个节点pxList-xListEnd是一个值需要取地址后强制类型转换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;//初始化链表节点计数器为0表示链表为空pxList-uxNumberOfItems (UBaseType_t)0U;
}3. 将新节点插入到链表尾部的函数
需要的步骤如下
拿出指向链表最后一个节点的指针将新的节点插入到原来最后节点的前面设置新插入节点所属的链表链表节点计数器
代码如下
//将节点插入到链表的尾部
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);
}
4. 将新节点按升序插入链表的函数
需要的步骤如下
定义迭代器节点指针用于查找插入的位置获取新插入节点的序号寻找节点插入的位置进行节点插入操作修改新插入的节点所在的链表链表节点计数器
代码如下
//将节点按照升序排列插入链表
void vListInsert(List_t * pxList, ListItem_t * const pxNewListItem)
{//1. pxIterator 用于查找插入位置ListItem_t * pxIterator;//2. 获取新插入节点的排序辅助值const TickType_t xValueOfInsertion pxNewListItem-xItemValue;//3. 寻找节点要插入的位置if(xValueOfInsertion portMAX_DELAY){ //如果是最大的节点插入在链表的最后即可pxIterator pxList-xListEnd.pxPrevious;}else{//for循环寻找插入位置//pxIterator (ListItem_t *)pxList-xListEnd 环状链表尾就是头for(pxIterator (ListItem_t *)pxList-xListEnd; pxIterator-pxNext-xItemValue xValueOfInsertion; pxIterator pxIterator-pxNext);}//4. 插入新节点pxNewListItem-pxNext pxIterator-pxNext;pxNewListItem-pxNext-pxPrevious pxNewListItem;pxNewListItem-pxPrevious pxIterator;pxIterator-pxNext pxNewListItem;//5. 修改插入的新节点所在的链表pxNewListItem-pvContainer (void *)pxList;//6. 链表节点计数器1(pxList-uxNumberOfItems);}5. 从链表中删除节点的函数
需要的步骤如下
获取要删除的节点所在的链表进行删除操作如果链表索引指向要删除的节点需更新索引使其指向要删除节点的前一个节点确保索引指向有效设置要删除节点的所属链表为空链表节点计数器–返回删除操作后链表中剩余的节点的数量
代码如下
//从链表中删除节点
UBaseType_t uxListRemove(ListItem_t * const pxItemToRemove)
{//1. 获取要删除的节点所在的列表List_t * const pxList (List_t *)pxItemToRemove-pvContainer;//2. 将节点从链表中删除pxItemToRemove-pxNext-pxPrevious pxItemToRemove-pxPrevious;pxItemToRemove-pxPrevious-pxNext pxItemToRemove-pxNext;//3. 如果要删除的节点是目前链表的索引就得把索引更新为要删除节点的前一个确保索引指向有效的节点if(pxList-pxIndex pxItemToRemove){pxList-pxIndex pxItemToRemove-pxPrevious;}//4. 将要删除的节点所属链表设置为空表示不属于任何链表pxItemToRemove-pvContainer NULL;//5. 更新链表节点计数器(pxList-uxNumberOfItems)--;//6. 返回链表中剩余的节点数量return pxList-uxNumberOfItems;
}三、宏定义
这些宏定义主要是为了方便链表操作
/*
************************************************************************
* 宏定义
************************************************************************
*/
/* 初始化节点的拥有者 */
#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 )
后记
如果您觉得本文写得不错可以点个赞激励一下作者 如果您发现本文的问题欢迎在评论区或者私信共同探讨 共勉