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的仿真功能,深入理解链表数据结构:

相关推荐
longlongzihan2 小时前
LeetCode 128. 最长连续序列 —— 从排序到哈希集合
数据结构·c++·算法·leetcode·排序算法·哈希表
mmmmath_32 小时前
二叉树の一些知识
数据结构·算法
程序员清风2 小时前
数据类型转换与日期时间处理
数据结构·pandas
Logic1014 小时前
C语言/数据结构位运算题解:异或XOR找出英雄队伍中的“独特战斗力“——只出现一次的数字
c语言·数据结构·数组·位运算·时间复杂度·算法题·异或性质
Cccp.1235 小时前
【leetcode】(九)哈希函数与哈希表
数据结构·leetcode·哈希算法
余额瞒着我当琳18 小时前
红黑树的实现--红黑树的概念、规则、效率、结构、旋转、查找、验证
数据结构·c++·算法
程序员南飞18 小时前
win系统安装minio
java·数据结构·算法
w_zero_one20 小时前
链表(4)
java·数据结构·算法
白山编程大哥1 天前
C语言篇:语法进阶
c语言·数据结构·算法