zoukankan      html  css  js  c++  java
  • 3、列表和列表项

    1.列表

    • 列表是FreeRTOSde中的一个数据结构,概念上和链表雷士,列表被用来跟踪FreeRTOS中的任务,与列表相关的全放在list.c和list.h中,在list.h中定义了一个结构体如下:
      typedef struct xLIST
      {
          listFIRST_LIST_INTEGRITY_CHECK_VALUE                //用来检查列表的完整性
          configLIST_VOLATILE UBaseType_t uxNumberOfItems;   //用来记录列表中列表项的数量  
          ListItem_t * configLIST_VOLATILE pxIndex;           //用来记录当前列表项索引号,用于遍历列表
          MiniListItem_t xListEnd;                            //列表中最后一个列表项,用来表示列表结束,,这是一个mini列表项
          listSECOND_LIST_INTEGRITY_CHECK_VALUE               //用来检查列表的完整性
       } List_t;

    2.列表项

    • 列表项就是存放在列表中的项目,FreeRTOS提供了两种列表项:列表项和迷你列表项,定义在list.h文件中;
    • 列表项,跟双链表相似
      struct xLIST_ITEM
      {
          listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE            //检查列表的完整性
          configLIST_VOLATILE TickType_t xItemValue;           //列表项值
          struct xLIST_ITEM * configLIST_VOLATILE pxNext;      //pxNext指向下一个列表项
          struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;  //pxPrevious指向前一个列表项
          void * pvOwner;                                      //记录此列表项归谁拥有,通常是任务控制块
          void * configLIST_VOLATILE pvContainer;              //用来记录此列表项归哪个列表
          listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE           //检查列表的完整性
      };
      typedef struct xLIST_ITEM ListItem_t;
    • 迷你列表项,定义在list.h文件中,如下:
      struct xMINI_LIST_ITEM
      {
          listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE            //检查迷你列表项的完整性
          configLIST_VOLATILE TickType_t xItemValue;           //记录列表项的值
          struct xLIST_ITEM * configLIST_VOLATILE pxNext;      //pxNext指向下一个列表项
          struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;  //pxPrevious指向上一个列表项
      };
      typedef struct xMINI_LIST_ITEM MiniListItem_t;
    • 列表项和迷你列表项的区别:迷你列表项别列表项少了几个成员变量;在有些情况下我们不需要列表项这么全的功能,可能只需其中的几个成员变量,如果此时使用列表项的话会造成内存浪费;

    3.列表初始化

    • 列表的初始化其实是初始化列表结构体List_t中的各个成员变量,列表通过vListInitialse()来完成,定于于list.c中
      void vListInitialise( List_t * const pxList )
      {
          pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd );            //xListEnd用来表示列表的末尾,pxIndex表示列表项的索引号
          pxList->xListEnd.xItemValue = portMAX_DELAY;                         //xListEnd根据MCU不同,值也不同,stm32为32位,所以 XListEnd为oxffffffffUL
          pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd );    //初始化列表项xListEnd的pxNext变量
          pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );//初始化列表项xListEnd的pxPrevious变量,指向xListEnd自身
          pxList->uxNumberOfItems = ( UBaseType_t ) 0U;                        //此时没有其他列表项,因此值为0(这里没有算xListEnd)
          listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList );                      //初始化列表项中用于完整性检查的字段,不同MCU值不同,32位系统为0x5a5a5a5aUL
          listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList );                      //初始化列表项中用于完整性检查的字段,不同MCU值不同,32位系统为0x5a5a5a5aUL

    4.列表项初始化

    • 列表项的初始化是通过vListInitialiseItem()来完成,定于于list.c中
      void vListInitialiseItem( ListItem_t * const pxItem )
      {    
          pxItem->pvContainer = NULL;        listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );    listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );}
    • 列表项的初始化比较简单,只需要将pvContainer的初始值设为NULL,并且给完整性检查的变量赋值即可;

    5.列表项插入

    • 列表项插入分为:头插入和尾插入。

    头插入

    • 通过函数VListInert()来完成,函数原型为:
      void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem ) //pxList:需要插入的列表, pxNewListItem:需要插入的列表项
    • 列表项的插入过程如图所示:

       

    尾插入

    • 通过函数vListInsertEnd()来实现,函数原型为:
      void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem ) //pxList:列表项要插入的列表, pxNewListItem:要插入的列表项
    •  尾插入过程如下图所示:

    6.列表项的删除 

    •  列表项的删除是通过uxListRemove()函数来完成的,函数原型为:
      UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) 
         //pxItemToRemove:要删除的列表项

    7.列表的遍历

    •  列表的遍历是通过listGET_OWNER_OF_NEXT_ENTRY()函数来实现的,每调用一次这个函数,列表的pxIndex变量就会指向下一个列表项,并返回这个列表项的pxOwner变量值,函数原型如下:
      //pxTCB:用来保存pxIndex所指向的列表项的pvOwner变量值
      //pxList:变量指向下一个列表项
      #define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList )

    8.程序验证

    •  部分程序如下所示:
      //list_task 任务
      void list_task(void *pvParameters);       // 任务函数
      #define list_task_zise 300                // 任务堆栈的大小
      #define list_task_prio 3                  // 任务优先级
      TaskHandle_t list_task_handler;           // 任务句柄
      
      // 定义一个列表和一个列表项
      List_t test_list;                         //定义一个列表
      ListItem_t test_listItem1;                //定义一个列表项test_listItem1
      ListItem_t test_listItem2;                //定义一个列表项test_listItem2
      ListItem_t test_listItem3;                //定义一个列表项test_listItem3
      
      void start_task( void * pvParameters )
      {
          taskENTER_CRITICAL();    // 创建临界区
          // 创建led1任务
          xTaskCreate((TaskFunction_t    )led1_task,
                      (const char *     )"led1_task",
                      (uint16_t        )start_task_zise,
                      (void *            )NULL,
                      (UBaseType_t    )led1_task_prio,
                      (TaskHandle_t * )&led1_task_handler);
          
          // 创建led2任务            
          xTaskCreate((TaskFunction_t    )list_task,
                      (const char *     )"list_task",
                      (uint16_t        )list_task_zise,
                      (void *            )NULL,
                      (UBaseType_t    )list_task_prio,
                      (TaskHandle_t * )&list_task_handler);
          vTaskDelete(start_task_handler); //删除开始任务
          taskEXIT_CRITICAL();    // 退出临界区
      }
      
      //list任务函数 
      void list_task( void * pvParameters )
      {
          vListInitialise(&test_list);             //初始化列表
          vListInitialiseItem(&test_listItem1);    //初始化列表项
          vListInitialiseItem(&test_listItem2);    //初始化列表项
          vListInitialiseItem(&test_listItem3);    //初始化列表项
          
          test_listItem1.xItemValue = 40;          //设置test_listItem1列表项值为40
          test_listItem2.xItemValue = 50;          //设置test_listItem2列表项值为50
          test_listItem3.xItemValue = 60;          //设置test_listItem3列表项值为60
          
          // 打印列表和其他列表项的地址
          printf("/*******************列表和列表项地址*******************/
      ");
          printf("项目                                    地址                    
      ");
          printf("test_list                              %#x                    
      ",(int)&test_list);
          printf("test_list->pxIndex                     %#x                    
      ",(int)test_list.pxIndex);
          printf("test_list->xListEnd                    %#x                    
      ",(int)(&test_list.xListEnd));
          printf("test_listItem1                         %#x                    
      ",(int)&test_listItem1);
          printf("test_listItem2                         %#x                    
      ",(int)&test_listItem2);
          printf("test_listItem3                         %#x                    
      ",(int)&test_listItem3);
          printf("/************************结束**************************/
      
      ");
      
          vListInsert(&test_list, &test_listItem1);    //插入列表项test_listItem1
          vListInsert(&test_list, &test_listItem2);    //插入列表项test_listItem2
          vListInsert(&test_list,&test_listItem3);     //插入列表项test_listItem3
          printf("/******************添加列表项test_listItem123*****************/
      ");
          printf("项目                                    地址                    
      ");
          printf("test_list->xListEnd->pxNext            %#x                    
      ",(int)(test_list.xListEnd.pxNext));
          printf("test_listItem1->pxNext                 %#x                    
      ",(int)(test_listItem1.pxNext));
          printf("test_listItem2->pxNext                 %#x                    
      ",(int)(test_listItem2.pxNext));
          printf("test_listItem3->pxNext                 %#x                    
      ",(int)(test_listItem3.pxNext));
          printf("/*******************前后向连接分割线********************/
      ");
          printf("test_list->xListEnd->pxPrevious        %#x                    
      ",(int)(test_list.xListEnd.pxPrevious));
          printf("test_listItem1->pxPrevious             %#x                    
      ",(int)(test_listItem1.pxPrevious));
          printf("test_listItem2->pxPrevious             %#x                    
      ",(int)(test_listItem2.pxPrevious));
          printf("test_listItem3->pxPrevious             %#x                    
      ",(int)(test_listItem3.pxPrevious));
          printf("/************************结束**************************/
      
      ");
          
          uxListRemove(&test_listItem2);                //删除列表项test_listItem2
          printf("/******************删除列表项test_listItem2*****************/
      ");
          printf("项目                                    地址                    
      ");
          printf("test_list->xListEnd->pxNext            %#x                    
      ",(int)(test_list.xListEnd.pxNext));
          printf("test_listItem1->pxNext                 %#x                    
      ",(int)(test_listItem1.pxNext));
          printf("test_listItem3->pxNext                 %#x                    
      ",(int)(test_listItem3.pxNext));
          printf("/*******************前后向连接分割线********************/
      ");
          printf("test_list->xListEnd->pxPrevious        %#x                    
      ",(int)(test_list.xListEnd.pxPrevious));
          printf("test_listItem1->pxPrevious             %#x                    
      ",(int)(test_listItem1.pxPrevious));
          printf("test_listItem3->pxPrevious             %#x                    
      ",(int)(test_listItem3.pxPrevious));
          printf("/************************结束**************************/
      
      ");
      
          test_list.pxIndex=test_list.pxIndex->pxNext;    //pxIndex向后移一项,这样pxIndex就会指向ListItem1。
          vListInsertEnd(&test_list,&test_listItem2);     //列表末尾添加列表项ListItem2
          printf("/******************添加列表项test_listItem2*****************/
      ");
          printf("项目                                   地址                    
      ");
          printf("test_list->xListEnd->pxNext            %#x                    
      ",(int)(test_list.xListEnd.pxNext));
          printf("test_listItem2->pxNext                 %#x                    
      ",(int)(test_listItem2.pxNext));
          printf("test_listItem1->pxNext                 %#x                    
      ",(int)(test_listItem1.pxNext));
          printf("test_listItem3->pxNext                 %#x                    
      ",(int)(test_listItem3.pxNext));
          printf("/*******************前后向连接分割线********************/
      ");
          printf("test_list->xListEnd->pxPrevious        %#x                    
      ",(int)(test_list.xListEnd.pxPrevious));
          printf("test_listItem2->pxPrevious             %#x                    
      ",(int)(test_listItem2.pxPrevious));
          printf("test_listItem1->pxPrevious             %#x                    
      ",(int)(test_listItem1.pxPrevious));
          printf("test_listItem3->pxPrevious             %#x                    
      ",(int)(test_listItem3.pxPrevious));
          printf("/************************结束**************************/
      
      ");
      }
    •  打印信息为:
      /*******************列表和列表项地址*******************/
      项目                                       地址                    
      test_list                              0x200000b4                    
      test_list->pxIndex                     0x200000bc                    
      test_list->xListEnd                    0x200000bc                    
      test_listItem1                         0x200000c8                    
      test_listItem2                         0x200000dc                    
      test_listItem3                         0x200000f0                    
      /************************结束**************************/
      
      /******************添加列表项test_listItem123*****************/
      项目                                       地址                    
      test_list->xListEnd->pxNext            0x200000c8                    
      test_listItem1->pxNext                 0x200000dc                    
      test_listItem2->pxNext                 0x200000f0                    
      test_listItem3->pxNext                 0x200000bc                    
      /*******************前后向连接分割线********************/
      test_list->xListEnd->pxPrevious        0x200000f0                    
      test_listItem1->pxPrevious             0x200000bc                    
      test_listItem2->pxPrevious             0x200000c8                    
      test_listItem3->pxPrevious             0x200000dc                    
      /************************结束**************************/
      
      /******************删除列表项test_listItem2*****************/
      项目                                       地址                    
      test_list->xListEnd->pxNext            0x200000c8                    
      test_listItem1->pxNext                 0x200000f0                    
      test_listItem3->pxNext                 0x200000bc                    
      /*******************前后向连接分割线********************/
      test_list->xListEnd->pxPrevious        0x200000f0                    
      test_listItem1->pxPrevious             0x200000bc                    
      test_listItem3->pxPrevious             0x200000c8                    
      /************************结束**************************/
      
      /******************添加列表项test_listItem2*****************/
      项目                                       地址                    
      test_list->xListEnd->pxNext            0x200000dc                    
      test_listItem2->pxNext                 0x200000c8                    
      test_listItem1->pxNext                 0x200000f0                    
      test_listItem3->pxNext                 0x200000bc                    
      /*******************前后向连接分割线********************/
      test_list->xListEnd->pxPrevious        0x200000f0                    
      test_listItem2->pxPrevious             0x200000bc                    
      test_listItem1->pxPrevious             0x200000dc                    
      test_listItem3->pxPrevious             0x200000c8                    
      /************************结束**************************/
  • 相关阅读:
    MySQL 中文显示乱码
    sprintf
    持续集成
    两个数据库中的数据同步问题(转)
    指针和引用的区别
    #define,const,typedef三者联系与区别
    [转载]selenium webdriver学习(八)
    PHPUnit学习安装
    CI是什么?
    图形界面的操作(转)
  • 原文地址:https://www.cnblogs.com/icefree/p/8689313.html
Copyright © 2011-2022 走看看