列表和列表项:
列表是FreeRTOS中的一个数据结构,用来跟踪FreeRTOS中的任务。
列表项就是存放在列表中的项目,属于列表的子集。
列表就相当于一个链表,列表项就相当于节点,在FreeRTOS中的列表是一个双向的环形链表。
列表的特点:
- 列表项之间的地址非连续的,是人为连接在一起的;
- 列表项的数目是由后期添加的个数决定的,随时可以改变。
在OS中任务的数量是不确定的,并且任务状态是会发生改变的,所以非常适合使用列表(链表)。
列表示意图:
- 开头和结尾的两个校验值是用来调试使用的,默认不开启;
- 成员
uxNumberOfltems
,用于记录列表中列表项的个数(不包含xListEnd); - 成员
pxlndex
用于指向列表中的某个列表项,一般用于遍历列表中的所有列表项; - 成员变量
xListEnd
是一个迷你列表项,排在最末尾。
列表项 :
- 成员变量
xltemValue
为列表项的值,用于按升序对列表中的列表项进行排序; - 成员变量
pxNext
和pxPrevious
分别用于指向列表项的下一个列表项和上一个列表项; - 成员变量
pxOwner
用于指向包含列表项的对象(通常是任务控制块); - 成员变量
pxContainer
用于指向列表项所在列表。
迷你列表项:
迷你列表项仅用于标记列表项的末尾和挂载其他插入列表中的列表项。
- 成员变量`xltemValue为列表项的值,用于按升序对列表中的列表项进行排序;
- 成员变量
pxNext
和pxPrevious
分别用于指向列表中列表项的下一个列表项和上一个列表项; - 迷你列表项只用于标记列表的末尾和挂载其他插入列表中的列表项,因此不需要成员变量
pxOwner
和pxContainer
,以节省内存开销。
列表相关的API函数:
初始化列表项vListInitalise():
void vListInitialise( List_t * const pxList )
{
pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd );//初始化时,列表中只有ListEnd,因此pxIndex指向xListEnd
pxList->xListEnd.xItemValue = portMAX_DELAY;//xListEnd的值初始化为最大值,用于列表项升序排序时,排在最后面
//初始化时,列表中只有xListEnd,因此上一个和下一个列表项都为xListEnd本身
pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd );
pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );
//初始化时,列表中的列表项数量为0(不包含xListEnd)
pxList->uxNumberOfItems = ( UBaseType_t ) 0U;
//初始化用于检测列表数据完整性的校验值
listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList );
listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList );
}
形参:pxList
描述:待初始化的列表
函数vListInitialiseItem():
void vListInitialiseItem( ListItem_t * const pxItem )
{
//初始化时,列表项所在列表设为空
pxItem->pxContainer = NULL;
//初始化用于检测列表数据完整性的校验值
listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
}
形参:pxItem
描述:待初始化列表项
函数vListInset():
void vListInset(List_t * const pxList,ListItem_t *const pxNewListItem)//用于将待插入列表项按照列表项的值升序进行排序,有序地插入到列表中
形参:
pxList表示列表;
pxNewListItem表示待插入列表项
void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem )
{
ListItem_t * pxIterator;
const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;//获取列表项的数值依据升序排序
listTEST_LIST_INTEGRITY( pxList );//检查参数是否正确
listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );
if( xValueOfInsertion == portMAX_DELAY )
{
pxIterator = pxList->xListEnd.pxPrevious;//插入位置为列表xListEnd前面
}
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->pxContainer = pxList;//更新待插入列表项所在表
( pxList->uxNumberOfItems )++;//更新列表中列表项的数量
}
函数vListInsertEnd():
void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem )
形参:
pxList表示要插入的列表;
pxNewListItem表示待插入的列表项
void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem )
{
//获取列表pxIndex指向的列表项
ListItem_t * const pxIndex = pxList->pxIndex;
listTEST_LIST_INTEGRITY( pxList );
listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );
/*更新待插入列表项的指针成员*/
pxNewListItem->pxNext = pxIndex;
pxNewListItem->pxPrevious = pxIndex->pxPrevious;
mtCOVERAGE_TEST_DELAY();
/*更新列表中原本列表项的指针成员变量*/
pxIndex->pxPrevious->pxNext = pxNewListItem;
pxIndex->pxPrevious = pxNewListItem;
/*更新待插入列表项的所在列表成员数量*/
pxNewListItem->pxContainer = pxList;
/*更新列表中列表项的数量*/
( pxList->uxNumberOfItems )++;
}
函数uxListRemove():
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
形参:
pxItemToRemove表示待移除的列表项
返回值:
整数,表示待移除列表项移除后,所在列表剩余列表项的数量
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
{
List_t * const pxList = pxItemToRemove->pxContainer;
/*从列表中移除列表项*/
pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;
pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;
mtCOVERAGE_TEST_DELAY();
/*如果pxIndex正指向待移除的列表项*/
if( pxList->pxIndex == pxItemToRemove )
{
/*pxIndex指向上一个列表项*/
pxList->pxIndex = pxItemToRemove->pxPrevious;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
/*将待移除的列表项的所在列表指针清空*/
pxItemToRemove->pxContainer = NULL;
/*更新列表中列表项的数量*/
( pxList->uxNumberOfItems )--;
/*返回移除后的列表中列表项的数量*/
return pxList->uxNumberOfItems;
}