lsit.h
首先是一些检查字节的宏定义开关
然后是ListItem_t 、MiniListItem_t 、List_t 结构的声明
最后是一些获取list内部参数的一些宏定义
着重介绍几个结构体声明和之后的几个宏定义
- ListItem_t
struct xLIST_ITEM
{
configLIST_VOLATILE TickType_t xItemValue; /*< 列表项的值, */
struct xLIST_ITEM * configLIST_VOLATILE pxNext; /*< 指针指向下一个列表项*/
struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; /*< 指针指向上一个列表项 */
void * pvOwner; /*<指向所在TCB, */
void * configLIST_VOLATILE pvContainer; /*<指向所在的列表*/
};
typedef struct xLIST_ITEM ListItem_t;
- MiniListItem_t
struct xMINI_LIST_ITEM
{//mini列表项,因为被设计时就是用来作为列表的列表尾的,所以不需要指向TCB、列表
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_t
typedef struct xLIST
{
configLIST_VOLATILE UBaseType_t uxNumberOfItems;//列表项元素个数
ListItem_t * configLIST_VOLATILE pxIndex; /*<列表项的index索引,可以用来遍历整个列表 */
MiniListItem_t xListEnd; /*< 列表的尾巴,可以想想为什么是miniListItem_t */
} List_t;
插入图片表示结构关系
实习公司电脑装这个软件太麻烦,下班或者实习完放
下面是一些操作列表或者列表项的一些宏
挑一个最长的吧
将下一个列表项指向的TCB地址取出来放到pxTCB中,不过可能遇到下一个列表项已经是尾列表项的可能,所以就是下下个列表项的pxTCB。
#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList ) \
{ \
List_t * const pxConstList = ( pxList ); //pxList是一个输入型参数,保证其不会被改变 \
( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; pxIndex指向下一个节列表项 \
if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) ) 如果下一个列表项已经是尾列表项了需要再往下一个节点走即走到了头结点\
{ \
( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; //往下一个节点走 \
} \
( pxTCB ) = ( pxConstList )->pxIndex->pvOwner; //将pvOwner给pxTCB \
}
list.c
一共是几个函数vListInitialise 、vListInitialiseItem 、 vListInsertEnd 、vListInsert 、 uxListRemove
- vListInitialise
void vListInitialise( List_t * const pxList )
{
/* 这个结构体包含了一个mini列表项,被标记作为尾列表项. */
pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd ); /*pxIndex 直接指向尾列表项 */
/* 给尾列表项的值最大,这样在后来插入列表项的时候永远都会排在最后,保证是尾列表项 */
pxList->xListEnd.xItemValue = portMAX_DELAY;
/* 由于是空列表项目,所以尾列表项的下一个和前一个列表项都只能指向自己. */
pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd );
pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );
//之所以用miniListItem_t来作为尾列表项,主要是因为节省内存RAM
pxList->uxNumberOfItems = ( UBaseType_t ) 0U;
/* 空列表,列表即使有尾列表项,列表项树木也是为0 */
}
- vListInitialiseItem
void vListInitialiseItem( ListItem_t * const pxItem )
{
/* 将列表项指向的列表置为NULL*/
pxItem->pvContainer = NULL;
}
- vListInsertEnd
void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem )
{//从Index节点前插入
ListItem_t * const pxIndex = pxList->pxIndex;
/* Insert a new list item into pxList, but rather than sort the list,
makes the new list item the last item to be removed by a call to
listGET_OWNER_OF_NEXT_ENTRY(). */
pxNewListItem->pxNext = pxIndex;
pxNewListItem->pxPrevious = pxIndex->pxPrevious;
/* Only used during decision coverage testing. */
mtCOVERAGE_TEST_DELAY();
pxIndex->pxPrevious->pxNext = pxNewListItem;
pxIndex->pxPrevious = pxNewListItem;
/* 记录列表项在哪个列表中. */
pxNewListItem->pvContainer = ( void * ) pxList;
( pxList->uxNumberOfItems )++;//列表项数量+1
}
- vListInsert
void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem )
{
ListItem_t *pxIterator;
const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
/* 将新的列表项按照 列表项的值 插入列表中,如果列表项的值等于portMAX_DELAY,则将其插入尾列表项的前面 */
if( xValueOfInsertion == portMAX_DELAY )
{
pxIterator = pxList->xListEnd.pxPrevious;
}
else
{
/**** NOTE ***********************************************************
从列表头遍历整个列表,如果遇到列表项值比待插入列表项值大的,就停止遍历,就在此插入新的列表项
**********************************************************************/
for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */
{
/* There is nothing to do here, just iterating to the wanted
insertion position. */
}
}
/*下面就是常见链表插入操作,读者自行理解*/
pxNewListItem->pxNext = pxIterator->pxNext;
pxNewListItem->pxNext->pxPrevious = pxNewListItem;
pxNewListItem->pxPrevious = pxIterator;
pxIterator->pxNext = pxNewListItem;
/* 记录列表项在哪个列表中. */
pxNewListItem->pvContainer = ( void * ) pxList;
( pxList->uxNumberOfItems )++;//列表项数量+1
}
/*-----------------------------------------------------------*/
- uxListRemove
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
{
/*pxItemToRemove 是已知肯定存在于列表中的,是从列表中获得的*/
List_t * const pxList = ( List_t * ) pxItemToRemove->pvContainer;
/*常规链表删除操作*/
pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;
pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;
/* 确保列表的index会指向一个有效的列表项,如果当前指向自己,将其指向前一个*/
if( pxList->pxIndex == pxItemToRemove )
{
pxList->pxIndex = pxItemToRemove->pxPrevious;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
/*将删除的列表项指向的列表指针置为NULL*/
pxItemToRemove->pvContainer = NULL;
( pxList->uxNumberOfItems )--;
/*返回剩余列表的列表项个数*/
return pxList->uxNumberOfItems;
}
list.c大概就是这样主要是list初始化,ListItem初始化,ListItem的插入,ListItem删除等函数操作。