FreeRTOS解析:List
受博客限制,如果您想获得更好的阅读体验,请前往https://github.com/Nrusher/FreeRTOS-Book或者https://gitee.com/nrush/FreeRTOS-Book下载PDF版本阅读,如果您觉得本文不错也可前往star,以示对作者的鼓励。如发现问题欢迎交流。PDF版效果如下
相关博客:
FreeRTOS解析:TCB_t结构体及重要变量说明(Task-1)
FreeRTOS解析:任务的创建(TASK-2)
链表这一数据结构是FreeRTOS的核心数据结构,有关任务调度、延时、阻塞、事件等操作都是通过对链表进行操作进而实现的。本章将详细分析源码文件list.c,list.h的内容,为后续的任务队列等的实现奠定基础。
链表及链表项结构体定义
FreeRTOS使用的链表结构是环形的双向链表,其链表项ListItem_t的定义如下
struct xLIST_ITEM
{
// 第一个和最后一个成员值当configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES被使能的时候会被设定为一个固定值,用来检验一个列表项数据是否完整
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;
这里如果使用configLIST_VOLATILE,其会被替换为volatile关键字,volatile关键字是让编译器不对该变量进行优化,所谓的优化可以理解为其在生成汇编时,若多次读取该变量时其可能会将变量值放入寄存器中以加快读取速度,而不是真正的读取,这使得当某个变量会快速变化时,优化后"读取"的值并不是变量真实的值。当使用volatile关键字时,其会强迫编译器每次使用该变量时都真正的对它进行一次读取。
#define configLIST_VOLATILE volatile
在链表项的结构体体构造中值得注意的是pvOwner和pxContainer这两个成员变量。pvOwner提供了一种可以快速访问由此链表项代表的对象的方法,pxContainer则提供了一种快速访问其所属链表的方法。这种处理方式大大提高了链表在任务调度等应用中的处理速度,提高系统效率。
Linux内核中也有侵入式的链表的设计,但其与FreeRTOS有不同之处,如果您对此感兴趣可以阅读相关问题: FreeRTOS相关:linux中的侵入式链表设计
由于在链表的尾部(头部),其链表项一般不需要有具体的内容,只需要提供下一个或前一个链表项的地址即可,因此为了节省RAM,FreeRTOS还定义了一个Mini链表项MiniListItem_t,其具体定义如下
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;
链表List_t的定义