freertos数据结构--链表

freertos内置链表库,以SWM320为例,链表库的数据结构如下:

①根节点数据结构

cpp 复制代码
//链表的数据结构
typedef struct xLIST
{
    listFIRST_LIST_INTEGRITY_CHECK_VALUE                /*用于检查链表是否损坏,我们没有开启检查功能,所以不存在这一行*/
    configLIST_VOLATILE UBaseType_t uxNumberOfItems;    //节点数
    ListItem_t * configLIST_VOLATILE pxIndex;            /* ?不明确是什么含义 */
    MiniListItem_t xListEnd;                            /* 猜测: 根节点,->pxNext 就是我们插入的第一个节点*/
    listSECOND_LIST_INTEGRITY_CHECK_VALUE                /*用于检查链表是否损坏,我们没有开启检查功能,所以不存在这一行*/
} List_t;

②节点数据结构

cpp 复制代码
//节点的数据类型
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;                                        /*这一个节点的主人 TCB*/
    void * configLIST_VOLATILE pvContainer;                /*指向节点所在的链表 */
    listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE            /*用于检查链表是否损坏,我们没有开启检查功能,所以不存在这一行*/
};

//类型重定义
typedef struct xLIST_ITEM ListItem_t;                    /* For some reason lint wants this as two separate definitions. */

//迷你版的节点数据类型
struct xMINI_LIST_ITEM
{
    listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE            /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
    configLIST_VOLATILE TickType_t xItemValue;            /*用于节点做排序 */
    struct xLIST_ITEM * configLIST_VOLATILE pxNext;
    struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;
};
//类型重定义
typedef struct xMINI_LIST_ITEM MiniListItem_t;

SWM320RET7库有着以下基本操作函数:

并且有一些链表的操作宏:

cpp 复制代码
//设置节点的主人 拥有者
#define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner )        ( ( pxListItem )->pvOwner = ( void * ) ( pxOwner ) )

//设置 节点的值
#define listSET_LIST_ITEM_VALUE( pxListItem, xValue )    ( ( pxListItem )->xItemValue = ( xValue ) )

//获取 节点的值
#define listGET_LIST_ITEM_VALUE( pxListItem )    ( ( pxListItem )->xItemValue )

//获取 表头节点的值
#define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList )    ( ( ( pxList )->xListEnd ).pxNext->xItemValue )

//获取 当前节点的下一个节点
#define listGET_NEXT( pxListItem )    ( ( pxListItem )->pxNext )

//获取 链表的最后一个节点
#define listGET_END_MARKER( pxList )    ( ( ListItem_t const * ) ( &( ( pxList )->xListEnd ) ) )

//判断链表是否为空
#define listLIST_IS_EMPTY( pxList )    ( ( BaseType_t ) ( ( pxList )->uxNumberOfItems == ( UBaseType_t ) 0 ) )

//获取链表的节点数
#define listCURRENT_LIST_LENGTH( pxList )    ( ( pxList )->uxNumberOfItems )

//获取链表第一个节点的 OWNER,明确是TCB
#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList )                                        \
{                                                                                            \
List_t * const pxConstList = ( pxList );                                                    \
    /* Increment the index to the next item and return the item, ensuring */                \
    /* we don't return the marker used at the end of the list.  */                            \
    ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext;                            \
    if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) )    \
    {                                                                                        \
        ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext;                        \
    }                                                                                        \
    ( pxTCB ) = ( pxConstList )->pxIndex->pvOwner;                                            \
}

//获取链表第一个节点的 OWNER 
#define listGET_OWNER_OF_HEAD_ENTRY( pxList )  ( (&( ( pxList )->xListEnd ))->pxNext->pvOwner )

下面看看怎么使用这个链表,我们把代码写在 task_start.c中:

分为尾部插入和排序插入:

cpp 复制代码
List_t mylist;        //链表根节点

void task_start_entry(void *arg)
{
    uint32_t tick = 0;
    printf("%s\r\n",__FUNCTION__);

    //初始化 myprintf
    cslock_init();
    //创建其他任务
    create_task_of_host();
    create_task_of_listen();
    create_task_of_ctrl();

    //在栈中(函数内)分配链表节点
    ListItem_t node0;
    ListItem_t node1;
    ListItem_t node2;

    //①初始化链表的根节点
    vListInitialise( &mylist ) ;

    //②初始化 所有节点
    vListInitialiseItem( &node0 );
    vListInitialiseItem( &node1 );
    vListInitialiseItem( &node2 );

    node0.xItemValue = 3;
    node1.xItemValue = 5;
    node2.xItemValue = 2;

    //③把这些节点插入到链表里面去
#if ( 0 )
    //排序插入
    vListInsert( &mylist,&node0 );
    vListInsert( &mylist,&node1 );
    vListInsert( &mylist,&node2 );


#else
    //插入到尾部
    vListInsertEnd( &mylist,&node0 );
    vListInsertEnd( &mylist,&node1 );
    vListInsertEnd( &mylist,&node2 );

#endif
    //④遍历链表,把所有元素都打印出来
    ListItem_t* node = listGET_HEAD_ENTRY( &mylist );
    while( 1 )
    {
        //如果当前的节点,就是链表的根节点 pxIndex ,说明就是表尾,表尾即退出循环
        if( node == mylist.pxIndex ) break;

        myprintf(" val = %08x\r\n",node->xItemValue );

        node = node->pxNext;
    }

    while(1)
    {
        vTaskDelay( pdMS_TO_TICKS( 1000 ) );
    }
}

我们可以借助MDK的仿真功能,深入理解链表数据结构:

相关推荐
BK贝壳14 小时前
亿级用户签到位图选型复盘:用 bool-hybrid-array 扛冷启动打卡,也把它和 Roaring/Redis 的边界测清楚了
数据结构·python·性能优化·numpy
挖井观天1 天前
《Java数据结构》第一讲:顺序表
数据结构
炘爚1 天前
数据结构算法总结
数据结构·python·算法
见叶之秋1 天前
【C++】红与黑的边界:红黑树从插入到自检
数据结构·c++·算法·面试
kiracrimson1 天前
string 容器:从 C 字符串到会自己扩容的类
开发语言·数据结构·c++·stl
CQU_JIAKE1 天前
10.25【A】
数据结构·算法
海清河晏1111 天前
加油站问题
数据结构·算法·leetcode
GG.WinGel1 天前
质数数目(蓝桥杯练习题)
java·数据结构·算法·青少年编程·蓝桥杯
敲代码的苦131 天前
头歌 数据结构—消防资源调度
数据结构·算法
ysu_03141 天前
【C++ 进阶之路】(二)从内联函数到类与对象:深挖内存对齐、this 指针与三大默认成员函数
开发语言·数据结构·c++·笔记·面向对象·this