数据结构
首先来看看双向链表结构体长什么样
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;
// 记录此 链表项 归谁拥有,通常是 TCB (任务控制块)
void * pvOwner;
// 拥有该 链表项 的 链表
struct xLIST * configLIST_VOLATILE pxContainer;
// 检验一个 链表项 数据是否完整
listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE
};
typedef struct xLIST_ITEM ListItem_t;
它的组织形式如下图所示

除此之外,还有一个MINI链表,但迷你列表项仅用于标记列表的末尾和挂载其他插入列表中的列表项,用户是用不到迷你列表项的,通常在在 list.h 文件中。
可以理解成专用于表示链表的尾节点的数据结构,即链表的尾巴。
/*MINI链表项
2024/11/6
ConstantZ
*/
struct xMINI_LIST_ITEM
{
// 检验一个 MINI链表项 数据是否完整
listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE
// 排序值
configLIST_VOLATILE TickType_t xItemValue;
// 下一个 链表项
struct xLIST_ITEM * configLIST_VOLATILE pxNext;
// 前一个 链表项
struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;
};
typedef struct xMINI_LIST_ITEM MiniListItem_t;
它的组织形式如下图所示

接下里介绍的数据结构就是包含上述两个数据结构的东西的完整链表,即xLIST,它的结构如下
typedef struct xLIST
{
// 检验一个 链表 数据是否完整
listFIRST_LIST_INTEGRITY_CHECK_VALUE
// 记录 链表 中 链表项 数目
volatile UBaseType_t uxNumberOfItems;
// 遍历 链表 的指针
ListItem_t * configLIST_VOLATILE pxIndex;
// 使用 MINI链表项 表示 链表尾部
MiniListItem_t xListEnd;
// 检验一个 链表 数据是否完整
listSECOND_LIST_INTEGRITY_CHECK_VALUE
} List_t;
xLIST由多个链表项构成的链表,每个链表项都挂载了一个任务。它的作用一般是区分不同任务状态或任务优先级,比如就绪状态的任务放在就绪链表中,阻塞状态的任务放在阻塞链表中,方便任务切换和管理.它的结构框图如下:

实现功能
实现的功能起始就是基础的 增删查改功能
初始化链表
- void vListInitialiseItem( ListItem_t * const pxItem )
初始化的时候该链表项未被任何链表包含,即初始化表示任何xLIST结构体变量都不拥有它(xMINI_LIST_ITEM)
void vListInitialiseItem( ListItem_t * const pxItem )
{
// 确保链表项未被记录在链表中
pxItem->pxContainer = NULL;
}
初始化xList结构体,即初始化链表,需要做四件事情
(1) 当前链表指针pxIndex指向末尾xListEnd
(2) 确保尾链表项 xListEnd 被排在链表最尾部 由代码可见是升序排序这些链表项的值的
(3) 将尾链表项 xListEnd 的前/后链表项指针均指向自己,因为初始化链表时只有尾链表项
(4) 初始化链表有0个链表项
void vListInitialise( List_t * const pxList )
{
// 链表当前指针指向 xListEnd
pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd );
// 设置链表尾链表项排序值为最大, 保证 xListEnd 会被放在链表的尾部
pxList->xListEnd.xItemValue = portMAX_DELAY;
// 尾链表项 xListEnd 的前/后链表项指针均指向自己
pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd );
pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );
// 初始化时链表中有 0 个链表项
pxList->uxNumberOfItems = ( UBaseType_t ) 0U;
}
执行完找个函数后,xList结构体内部的值如下

尾部插入链表项
即我们在链表项的最后插入链表项。代码实现如下
void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem )
{
// 获取链表中当前指针 pxIndex 位置
ListItem_t * const pxIndex = pxList->pxIndex;
// 1. 改变自身 pxNext 和 pxPrevious
pxNewListItem->pxNext = pxIndex;

最低0.47元/天 解锁文章
848

被折叠的 条评论
为什么被折叠?



