我是靠谱客的博主 犹豫帽子,最近开发中收集的这篇文章主要介绍FreeRTOS的列表和列表项,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

列表和列表项作为FreeRTOS源码的基本数据结构,相当于数据结构中的循环双链表。

1.定义:关于这部分的数据主要有三种结构(列表、列表项、迷你列表项)

列表

typedef struct xList
{
    listFIRST_LIST_INTEGRITY_CHECK_VALUE        //检查列表的完整性,是宏定义
    configLIST_VOLATILE UBaseType_t    uxNumberOfItems;    //记录列表中列表项的数量
    ListItem_t* configLIST_VOLATILE    pxIndex;            //记录当前列表项的索引号,用于遍历列表
    MiniListItem_t                     xListEnd;            //列表中最后一个列表项
    listSECOND_LIST_INTEGRTIY_CHECK_VALUE        //检查列表的完整性,是宏定义
}List_t;

列表项:

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
{
    listFITRST_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;

2、基本操作:

一般链表的操作包括链表的创建(初始化)、插入、删除、查找。

列表和列表项初始化:

//列表初始化
void vListInitialise(List_t* const pxList)
{
    pxList->pxIndex = (ListItem_t *) &(pxList->xListEnd);
    pxList->xListEnd.xItemValue = portMAX_DELAY;    //portMAX_DELAY是个宏定义,STM32中式0xffffffffUL,表示列表数量的最大值
    pxList->xListEnd.pxNext = (ListItem_t *) &(pxList->xListEnd);    //列表项的下一项指向自身
    pxList->xListEnd.pxPrevious = (ListItem_t *) &(pxList->xListEnd);
    pxList->uxNumberOfItems = (UBaseType_t) 0U;    //当前列表中的列表项为0,自身不算
    //如果configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES被置为1,执行下面语句
    list_SET_LIST_INTEGRITY_CHECK_1_VALUE(pxList);
    list_SET_LIST_INTEGTITY_CHECK_2_VALUE(pxList);    
}

//列表项初始化
void vListInitialiseItem(ListItem_t* const pxItem)
{
    pxItem->pvContainer = NULL;
    
    listSET_FIRST_LIST_ITEM_ INTEGRITY_CHECK_VALUE(pxItem);
    listSET_FIRST_LIST_ITEM_INTERITY_CHECK_VALUE(pxItem);
}

列表项插入:

/*功能:向列表中插入列表项
 *参数: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;
    }
    else
    {
    //按顺序查找要插入的位置
        for(pxIterator = (ListItem_t* )&(pxList->xListEnd); pxIterator->
            pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext)
        {
        
        }
    }

    pxNewListItem->pxNext = pxIterator->pxNext;    //将新节点的后一个节点指向原来pxIterator的后一个节点
    pxNewListItem->pxNext->pxPrevious = pxNewListItem;    //将新节点的后一个节点的前一个指针指向新节点
    pxNewListItem->pxPrevious = pxIterator;         //将新节点的上一个节点指向原来的节点
    pxIterator->pxNext = pxNewListItem;            //将原来节点的下一个节点指针指向新节点
    
    pxNewListItem->pvContainer = (void*) pxList;    //新节点属于的队列
    (pxList->uxNumberOfItems)++;                    //节点数加一

}

列表末尾插入:

void vListInsertEnd(List_t* const pxList, ListItem_t* const pxNewListItem)
{
    ListItem_t* const pxIndex = pxList->pxIndex;    //当前列表中所指向的列表项
    
    listTEST_LIST_INTEGRITY(pxList);                //检查列表的完整性
    listTEST_LIST_ITEM_INTEGRITY(pxNewListItem);    //检查列表项的完整性

    pxNewListItem->pxNext = pxIndex;                //将新列表项的下一项指向列表头pxIndex
    pxNewListItem->previous = pxIndex->pxPrevious;
    
    mtCOVERAGE_TEST_DELAY();
    
    pxIndex->pxPrevious->pxNext = pxNewListItem;    //将列表尾指向新列表
    pxIndex->pxPrevious = pxNewListItem;            //将原来的头列表的上个节点指向新列表
    
    pxNewListItem->pvContainer = (void *)pxList;

    (pxList->uxNumberOfItems)++;
}

列表项的删除操作:

UBaseType_t uxListRemove(ListItem_t* const pxItemToRemove)
{
    List_t* const pxList = (List_t*)pxItemToRemove->pvContainer;    //确定所在列表
    pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;
    pxItemToRemove->pxPrevious->next = pxItemToRemove->pxNext;

    mCOVERAGE_TEST_DELAY();
    
    if(pxList->pxIndex == pxItemToRemove)    //如果删除的是表头
    {
        pxList->pxIndex = pxItemToRemove->pxPrevious;
    }
    else
    {
        mtCOVERAGE_TEST_MARKER();
    }

    pxItemToRemove->pvContainer = NULL;
    (pxList->uxNumberOfItems)--;

    return pxList->uxNumberOfItems;
}

列表的遍历:listGET_OWNER_OF_NEXT_ENTRY(pxTCB, pxList)

该函数是利用列表中pxIndex项来遍历整个列表,大家可以试试。

最后

以上就是犹豫帽子为你收集整理的FreeRTOS的列表和列表项的全部内容,希望文章能够帮你解决FreeRTOS的列表和列表项所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(52)

评论列表共有 0 条评论

立即
投稿
返回
顶部