FreeRTOS中的列表和列表项类似于数据结构中的链表和节点;

相关的文件是list.c和list.h两个文件;

List_t列表结构体

具体定义如下:

/*
* Definition of the type of queue used by the scheduler.
*/
typedef struct xLIST
{
listFIRST_LIST_INTEGRITY_CHECK_VALUE
volatile UBaseType_t uxNumberOfItems;
ListItem_t * configLIST_VOLATILE pxIndex;
MiniListItem_t xListEnd;
listSECOND_LIST_INTEGRITY_CHECK_VALUE
} List_t;

在上述结构体中:

  • listFIRST_LIST_INTEGRITY_CHECK_VALUElistSECOND_LIST_INTEGRITY_CHECK_VALUE两个成员,是用来检查列表完整性的,如果使用需要将宏configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES设置为1,之后会将这两个成员分别用xListIntegrityValue1xListIntegrityValue2替换,并且在初始化函数vListInitialise()中给这两个成员变量设置一个特殊的值,一般默认不使用
  • uxNumberOfItems是一个unsigned long类型的变量,用于记录列表中列表项的个数;
  • pxIndex用来记录当前列表项索引值,用于遍历列表;
  • xListEnd列表中最后一个列表项,用来表示列表结尾,该变量的类型是一个Mini列表项类型;

xLIST_ITEM列表项结构体

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;
struct xLIST * configLIST_VOLATILE pxContainer;
listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE
};
typedef struct xLIST_ITEM ListItem_t;

在上述结构体中:

  • 第一个成员和最后一个成员,用来检查列表项完整性的,与列表结构体中的作用类似;
  • xItemValue为列表项值;
  • pxNext指向下一个列表项和pxPrevious配合实现类似双向链表的功能;
  • pvOwner记录该列表项的拥有者,通常是任务块;
  • pxContainer记录此列表项归哪个列表;

xMINI_LIST_ITEM迷你列表项结构体

struct xMINI_LIST_ITEM
{
listFIRST_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;

迷你列表项和列表项结构体区别就是少了几个成员变量,之所以如此定义是因为有些情况下不需要列表项中的部分变量;

列表的初始化

列表是通过vListInitialise()函数初始化的,源码定义如下:

void vListInitialise( List_t * const pxList )
{
pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd );
pxList->xListEnd.xItemValue = portMAX_DELAY;
pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd );
pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );
pxList->uxNumberOfItems = ( UBaseType_t ) 0U;
listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList );
listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList );
}

对于listSET_LIST_INTEGRITY_CHECK_1_VALUElistSET_LIST_INTEGRITY_CHECK_2_VALUE两项默认不使用,所以整个列表初始化之后的示意图如下:

  • 由于目前还没有列表项所以uxNumberOfItems变量初始化为0;

  • pxIndex指向列表结构体xLIST中内嵌的xListEnd迷你列表项;

  • 列表项xListEnd中成员变量xItemValue初始化为portMAX_DELAY,portMAX_DELAY是一个宏,定义在portmacro.h文件中,根据使用的MCU不同,对应的值也不同,定义如下:

    #if( configUSE_16_BIT_TICKS == 1 )
    #define portMAX_DELAY ( TickType_t ) 0xffff
    #else
    #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
    #endif
  • pxNext和pxPrevious都指向自身,也就是xListEnd;

列表项的初始化

void vListInitialiseItem( ListItem_t * const pxItem )
{
/* Make sure the list item is not recorded as being on a list. */
pxItem->pxContainer = NULL; /* Write known values into the list item if
configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
}

主要是将成员变量pxContainer指向NULL;

列表插入操作

列表插入函数有两个,分别是vListInsertEnd()和vListInsert()函数;

vListInsertEnd()函数是往列表的末尾添加列表项的,列表中的xListEnd成员变量表示末尾,那么该函数插入一个列表项是不是就是插入到xListEnd的前面或者后面?这个不一定;

所谓的末尾要根据列表的成员变量pxIndex来确定的

pxIndex成员变量是用来遍历列表的,它所指向的列表项就是要遍历的开始列表项,也就是列表的头部,由于是个环形列表,所以新的列表项就应该插入到pxIndex所指向的列表项的前面,这才是真正意义上的尾部;

vListInsert()函数是向列表中插入一个列表项,插入的位置由列表项成员变量xItemValue决定

如果xItemValue的值是portMAX_DELAY,那么就直接将列表项插入到xListEnd的前面;

如果xItemValue的值不等于portMAX_DELAY,那么这个要插入的位置根据xItemValue的值按照升序的方式在列表中一个个找,直到最终确定位置插入列表项;

列表项的删除

列表项的删除是由函数uxListRemove()实现的,整个过程的操作如下:

  • 从传入的要删除的列表项中读取成员变量pxContainer得到该列表项处于哪个列表中;
  • 断开该列表项的前后“连接”,即删除;
  • 如果列表的pxIndex正好指向要删除的列表项,那么在删除列表项以后重新给pxIndex找个新的指向,这个新的指向就是被删除列表项的前一个列表项;
  • 将被删除的列表项的成员变量pxContainer指向NULL;
  • 返回新列表当前的列表项数目;

列表的遍历

FreeRTOS提供了一个函数来完成列表的遍历,就是listGET_OWNER_OF_NEXT_ENTRY(),这个函数本质上是一个宏,没调用一次这个函数列表的pxIndex变量就会指向下一个列表项,并且通过pxTCB传出这个列表项的pvOwner变量值;

此函数用于从多个同优先级的就绪任务中查找下一个要运行的任务

最新文章

  1. VM~Linux联不上网
  2. [译]line clampin让文字在指定的行数内省略号显示
  3. Nine Great Books about Information Visualization
  4. 教学项目之-通过Python实现简单的计算器
  5. D3画图学习一
  6. Accordion( 分类) 组件
  7. 【JAVA编码专题】深入分析 Java 中的中文编码问题
  8. 一劳永逸让windows 64位操作系统 禁止强制驱动签名
  9. Java环境变量详解
  10. SVN Upgrade working copy
  11. Java-transient总结
  12. [转]Jmeter + Grafana + InfluxDB 性能测试监控
  13. windows 命令行操作 Mysql 数据库
  14. TensorFlow 2.0 新特性
  15. 微软Power BI 每月功能更新系列——6月Power BI 新功能学习
  16. css美化select标签,兼容ie10 ie10+,chrome。但不支持ie9 ie9-
  17. 基于Hadoop2.6.5(HA)的Hive1.2.1的MySQL方式配置
  18. 牛客网多校赛第七场--C Bit Compression【位运算】【暴力】
  19. git 使用手册
  20. 洛谷 P2146 [NOI2015]软件包管理器 (树链剖分模板题)

热门文章

  1. jsplumb 流程图,常用功能配置记录
  2. redis 内存数据库
  3. ES6-类(Class)
  4. super的实例及实现原理
  5. MAVEN(二)
  6. 【转帖】史上最全PostgreSQL体系结构
  7. 《Mysql - 为什么表数据删掉一半,表文件大小不变?》
  8. 剑指offer30:连续子数组的最大和
  9. eclipse New菜单项的显示问题
  10. Session和Cookie的原理