本文将系统的介绍下列表和列表项的基础,关系,一些底层逻辑等
结构体(在list.h中):
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; //检查列表完整性
};
typedef struct xLIST_ITEM ListItem_t;
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; //下一列表项
};
typedef struct xMINI_LIST_ITEM MiniListItem_t;
?以上两种的区别其实并不大,就在于他们所占的内存空间
结构体(在list.h中):
typedef struct xLIST
{
listFIRST_LIST_INTEGRITY_CHECK_VALUE //检查列表完整性
configLIST_VOLATILE UBaseType_t uxNumberOfItems; //记录列表中列表项的个数(但下面的成员xListEnd并不算在其中,即:xListEnd在创建列表时就存在,但此时uxNumberOfItems=0)
ListItem_t * configLIST_VOLATILE pxIndex; //用于检索列表项,指向着某个列表项
MiniListItem_t xListEnd; //最后的列表项,且始终在最后
listSECOND_LIST_INTEGRITY_CHECK_VALUE //检查列表完整性
} List_t;
????????
在 二 中说到,pvOwner 变量表示该列表项归谁所有的,那么具体代码实现(从创建任务开始,到具体实现,具体可自行查找相关函数):
创建任务( xTaskCreate() )——>对任务进行初始化( prvInitialiseNewTask() )——>设定列表项的Owner( listSET_LIST_ITEM_OWNER( &( pxNewTCB->xStateListItem ), pxNewTCB ); )。
最后goto下?listSET_LIST_ITEM_OWNER(); 这个函数,即可看到其具体实现:
pxListItem )->pvOwner = ( void * ) ( pxOwner )
函数在 list.c 中:
void vListInitialise( List_t * const pxList )
{
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 );
}
需要注意的几点:
列表中 xListEnd 成员被赋予的值:0xffffffffUL
列表中?xListEnd 的两个指针都指向了自己
列表中的?uxNumberOfItems 初值为0,即一开始时并没有将 xListEnd 算作列表项中的一个
插入有两个函数:
vListInsert(?List_t * const pxList, ListItem_t * const pxNewListItem );
vListInsertEnd( List_t * const pxList,? ListItem_t * const pxNewListItem ) ;
这两个函数的区别为:
vListInsert()::插入列表项时,是按照?xItemValue 的大小升序插入的,所以?xListEnd 永远是列表项的最后一个
vListInsertEnd():?插入列表项时,是直接插入到列表末尾的
listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList );