1. 列表和列表项概念
1.1 对C语言中链表的简介
在FreeRTOS中,列表和列表项是非常重要的数据结构,它跟C语言中的链表很相似。在C语言中,链表包括单链表、单循环链表、双向循环链表,如下:
在FreeRTOS中,采用的是双项循环链表,对于双项循环链表,有:
- 链表中包含一个表头(也称头结点)和多个结点,若链表中仅有一个表头,结点数为0,称为空表。
- 每个结点包含两个指针域和储存信息域。其中,两个指针域中一个指向前结点,一个指向后结点。第一个结点和最后一个结点有点特殊,如图3所示,结点1的前结点为表头,后结点为结点2;结点4的前结点为结点3,后结点为表头。储存信息域包含储存的可用数据,一般可在该处设置指针,将其指向储存数据处。
- 表头跟结点不同,它一般只需要包含两个指针域,不需要储存信息域。在实际应用中,在表头中也会加入链表的状态信息,如结点的总数、遍历整个链表的指针等信息。
- 表头位置固定不变,当对链表进行插入或删除等操作,其本质是对链表中结点进行插入或删除。
- 表头和结点的数据成员不同,在实际应用中,一般会定义两个不同的数据类型(结构体),分别用于表头和结点。
- 在循环链表中,有些特殊操作不设置链表表头,而直接设置表尾,如两个链表合并时,仅需一个表的表头与另一个表的表尾相连。双项循环列表是一个圈,对于直接设置表尾这种情况,其理解方式可以看成表头一样。
1.2 FreeRTOS中列表和列表项的理解
理解了C语言中的双向循环链表,就很好理解FreeRTOS中的列表和列表项。
在FreeRTOS中,列表和列表项的数据结构声明和函数定义的源代码都在list.c和list.h中。在list.h中存在三个重要的结构体声明,分别是:
struct xLIST //列表
struct xLIST_ITEM //列表项
struct xMINI_LIST_ITEM //Mini列表项
其中,列表相当于链表,Mini列表项相当于表头,列表项相当于双向链表中的结点。在定义列表时,Mini列表项定义为xListEnd,从字面上看,它表示列表中最后一个列表项。由于链表中是一个圈,首就是尾,尾就是首,可以将其理解为表头,但是定义为xListEnd。另外,在定义一个列表时,其本质是定义一个表头,如果对列表的操作,就是对列表中的列表项操作。
在FreeRTOS中,列表的结构体声明如下:
typedef struct xLIST
{
listFIRST_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
configLIST_VOLATILE UBaseType_t uxNumberOfItems;
ListItem_t * configLIST_VOLATILE pxIndex; /*< Used to walk through the list. Points to the last item returned by a call to listGET_OWNER_OF_NEXT_ENTRY (). */
MiniListItem_t xListEnd; /*< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */
listSECOND_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
} List_t;
其中:
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;
即列表的结构为:
通过分析列表的结构体声明可知:
- uxNumberOfItems、pxIndex和Mimi列表项组成一个完整列表的“表头”,其中包括列表的状态信息,如uxNumberOfItems表示列表中列表项的数目、pxIndex表示索引,Mimi列表项主要包含指针域,分别指向前一个列表项和后一个列表项。
- MiniListItem_t(Mimi列表项)被包含在List_t(列表)里,它被命名为xListEnd,从字面上可知,它表示列表的最后一个列表项。由于在链表中是首尾相连,首就是尾,尾就是首,可将其理解为表头,但是定义为xListEnd。
- 列表(List_t)中表示列表的表头,如果列表项为0,称为空列表。对某个列表的插入和删除,其本质对列表项的插入和删除。
2. 列表和列表项源代码分析
2.1 列表项
struct xLIST_ITEM
{
listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE (1)
configLIST_VOLATILE TickType_t xItemValue; (2)
struct xLIST_ITEM * configLIST_VOLATILE pxNext; (3)
struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; (4)
void *