FreeRTOS-列表和列表项

FreeRTOS使用双向环形链表实现列表来跟踪任务,列表项作为链表节点。列表项数目可变,适配任务数量不确定和状态变化的需求。列表包含头尾校验值、列表项计数和指针,列表项包含值、前后指针和对象引用。初始化、插入、删除等API确保列表有序和高效操作。
摘要由CSDN通过智能技术生成

列表和列表项:

列表是FreeRTOS中的一个数据结构,用来跟踪FreeRTOS中的任务。
列表项就是存放在列表中的项目,属于列表的子集。
列表就相当于一个链表,列表项就相当于节点,在FreeRTOS中的列表是一个双向的环形链表。

列表的特点:
  • 列表项之间的地址非连续的,是人为连接在一起的;
  • 列表项的数目是由后期添加的个数决定的,随时可以改变。

在OS中任务的数量是不确定的,并且任务状态是会发生改变的,所以非常适合使用列表(链表)。

列表示意图:

在这里插入图片描述

  • 开头和结尾的两个校验值是用来调试使用的,默认不开启;
  • 成员uxNumberOfltems,用于记录列表中列表项的个数(不包含xListEnd);
  • 成员pxlndex用于指向列表中的某个列表项,一般用于遍历列表中的所有列表项;
  • 成员变量xListEnd是一个迷你列表项,排在最末尾。
    在这里插入图片描述

列表项 :

在这里插入图片描述

  • 成员变量xltemValue为列表项的值,用于按升序对列表中的列表项进行排序;
  • 成员变量pxNextpxPrevious分别用于指向列表项的下一个列表项和上一个列表项;
  • 成员变量pxOwner用于指向包含列表项的对象(通常是任务控制块);
  • 成员变量pxContainer用于指向列表项所在列表。
    在这里插入图片描述

迷你列表项:

迷你列表项仅用于标记列表项的末尾和挂载其他插入列表中的列表项。
在这里插入图片描述

  • 成员变量`xltemValue为列表项的值,用于按升序对列表中的列表项进行排序;
  • 成员变量pxNextpxPrevious分别用于指向列表中列表项的下一个列表项和上一个列表项;
  • 迷你列表项只用于标记列表的末尾和挂载其他插入列表中的列表项,因此不需要成员变量pxOwnerpxContainer,以节省内存开销。
    在这里插入图片描述

列表相关的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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值