本博客中部分图片,来自《FreeRTOS开发手册》(正点原子)。
列表与列表项是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. */
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;
列表的第一项和最后一项是用来检查列表完整性的,当configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES
被置为1的时候,会向这两个变量写入0x5a5a5a5aUL
,默认不开启。那么我们将剩下的三项图表化:
第一项是当前列表共有多少列表项(迷你列表项不计入其中)。第二个是一个列表项指针。第三项是迷你列表项,那么从数据结构将上图转化为:
这样一来,学过数据结构的同学想必就非常熟悉了,这就是一个典型的双向链表。
列表项
列表项定义如下:
struct xLIST_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; /*< The value being listed. In most cases this is used to sort the list in descending order. */
struct xLIST_ITEM * configLIST_VOLATILE pxNext; /*< Pointer to the next ListItem_t in the list. */
struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; /*< Pointer to the previous ListItem_t in the list. */
void *pvOwner; /*< Pointer to the object (normally a TCB) that contains the list item. There is therefore a two way link between the object containing the list item and the list item itself. */
struct xLIST * configLIST_VOLATILE pxContainer; /*< Pointer to the list in which this list item is placed (if any). */
listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
};
同样的,第一项和最后一项是用来检查列表完整性的。
- xItemValue :这一项是uint32_t类型的值。链表项根据这个值从小到大排列。
- pxNext:指向下一个列表项的指针。
- pxPrevious:指向上一项列表项的指针。
- pvOwner:指向这个列表项的任务项。
- pxContainer:指向这个列表项所在链表的列表。(这一句比较绕,请区分列表与链表的区别。)
列表与列表项操作
列表与列表项底层是用链表实现的,它们的操作与链表相同。
初始化
- 链表中共有0个列表项。(迷你列表项不计入其中。)
pxIndex
指向迷你列表项。- 迷你列表项的
xItemValue
赋予最大值,以确保其位于链表的最后一项。 - 迷你列表项的
pxNext
和pxContainer
都指向迷你列表项本身。
结果如图:
列表项插入
列表项插入共有两个函数vListInsertEnd
与vListInsert
。两个函数的区别是,第一个函数会把列表项插入到迷你列表项之前。而第二个函数会按照列表项中的xItemValue
将列表项从小到大插入到适当的位置。
其余操作与双向链表操作相同,这里不再赘述,会和列表项删除操作一起给出图示。
列表项删除
列表项删除与双向链表删除操作相同。这里给出图示:
有三个列表项的链表。