

1. 如同列表一样,列表项中也包含了两个用于检测列表项数据完整性的宏定义。
2. 成员变量 xItemValue 为列表项的值,这个值多用于按升序对列表中的列表项进行排序。
3. 成员变量 pxNext 和 pxPrevious 分别用于指向列表中列表项的下一个列表项和上一个列 表项。
4. 成员变量 pxOwner 用于指向包含列表项的对象(通常是任务控制块),因此,列表项和 包含列表项的对象之间存在双向链接。
5. 成员变量 pxContainer 用于指向列表项所在列表。
列表项的结构示意图,如下图所示:

1. 迷你列表项中也同样包含用于检测列表项数据完整性的宏定义。
2. 成员变量 xItemValue 为列表项的值,这个值多用于按升序对列表中的列表项进行排序。
3. 成员变量 pxNext 和 pxPrevious 分别用于指向列表中列表项的下一个列表项和上一个列 表项。
4. 迷你列表项相比于列表项,因为只用于标记列表的末尾和挂载其他插入列表中的列表项, 因此不需要成员变量 pxOwner 和 pxContainer,以节省内存开销。 迷你列表项的结构示意图,如下图所示:
FreeRTOS 列表和列表项相关 API 函数
FreeRTOS 中列表和列表项相关的 API 函数如下表所示:
函数 vListInitialise()
此函数用于初始化列表,在定义列表之后,需要先对其进行初始化,只有初始化后的列表, 才能够正常地被使用。列表初始化的过程,其实就是初始化列表中的成员变量。函数原型如下 所示:
函数 vListInitialise()的形参描述,如下表所示:
函数 vListInitialise()无返回值。 函数 vListInitialise()在 list.c 文件中有定义,具体的代码如下所示:
函数 vListInitialise()初始化后的列表结构示意图,如下图所示:
函数 vListInitialiseItem()
此函数用于初始化列表项,如同列表一样,在定义列表项之后,也需要先对其进行初始化, 只有初始化有的列表项,才能够被正常地使用。列表项初始化的过程,也是初始化列表项中的成员变量。函数原型如下所示:
函数 vListInitialiseItem()的形参描述,如下表所示:
函数 vListInitialiseItem()无返回值。 函数 vListInitialiseItem()在 list.c 文件中有定义,具体的代码如下所示:
这个函数比较简单,只需将列表项所在列表设置为空,以保证列表项不再任何一个列表项 中即可。函数 vListInitialiseItem()初始化后的列表项结构示意图,如下图所示:
函数 vListInsertEnd()
此函数用于将待插入列表的列表项插入到列表 pxIndex 指针指向列表项的前面,是一种无 序的插入方法。函数原型如下所示:
函数 vListInsertEnd()的形参描述,如下表所示:
函数 vListInsertEnd()无返回值。 函数 vListInsertEnd()在 list.c 文件中有定义,具体的代码如下所示:
从上面的代码可以看出,此函数就是将待插入的列表项插入到列表 pxIndex 指向列表项的 前面,要注意的时,pxIndex 不一定指向 xListEnd,而是有可能指向列表中任意一个列表项。函 数 vListInsertEnd()插入列表项后的列表结构示意图,如下图所示:
函数 vListInsert()
此函数用于将待插入列表的列表项按照列表项值升序排序的顺序,有序地插入到列表中。 函数原型如下所示:
函数 vListInsert()无返回值。
函数 vListInsert()在 list.c 文件中有定义,具体的代码如下所示:
从上面的代码可以看出,此函数在将待插入列表项插入列表之前,会前遍历列表,找到待 插入列表项需要插入的位置。待插入列表项需要插入的位置是依照列表中列表项的值按照升序排序确定的。函数 vListInsert()插入列表项后的列表结构示意图,如下图所示:
函数 uxListRemove()
此函数用于将列表项从列表项所在列表中移除,函数原型如下所示:
函数 uxListRemove()的形参描述,如下表所示:
函数 uxListRemove()的返回值,如下表所示:
函数 uxListRemove()在 list.c 文件中有定义,具体的代码如下所示:
要注意的是函数 uxListRemove()移除后的列表项,依然于列表有着单向联系,即移除后列 表项中用于指向上一个和下一个列表项的指针,依然指向列表中的列表项。函数 uxListRemove() 移除列表项后的列表结构示意图,如下图所示:
FreeRTOS 操作列表和列表项的宏
在 list.h 文件中定义了大量的宏,用来操作列表以及列表项,如下表所示:
FreeRTOS 列表项的插入与删除实验
首先是测试列表和列表项的定义:
List_t TestList;
ListItem_t ListItem1;
ListItem_t ListItem2;
ListItem_t ListItem3;
然后是具体的代码操作逻辑:
void task1_task(void *pvParameters)
{
vListInitialise(&TestList);
vListInitialiseItem(&ListItem1);
vListInitialiseItem(&ListItem2);
vListInitialiseItem(&ListItem3);
printf("\r\n");
printf("打印列表和列表项的地址\r\n");
printf("项目\t\t\t地址\r\n");
printf("\r\n");
printf("TestList地址\r\n");
printf("TestList\t\t0x%p\t\r\n", &TestList);
printf("TestList->pxIndex\t0x%p\t\r\n", TestList.pxIndex);
printf("TestList->xListEnd\t0x%p\t\r\n", (&TestList.xListEnd));
printf("TestList->uxNumberOfItems\t%ld\t\r\n", TestList.uxNumberOfItems);
printf("\r\n");
printf("列表项地址\r\n");
printf("ListItem1\t\t0x%p\t\r\n", &ListItem1);
printf("ListItem2\t\t0x%p\t\r\n", &ListItem2);
printf("ListItem3\t\t0x%p\t\r\n", &ListItem3);
printf("\r\n");
printf("在TestList列表中插入列表项1,2,3,xItemValue的值为1,2,3\r\n");
ListItem1.xItemValue = 1;
ListItem2.xItemValue = 2;
ListItem3.xItemValue = 3;
vListInsert((List_t *)&TestList, (ListItem_t *)&ListItem1);
vListInsert((List_t *)&TestList, (ListItem_t *)&ListItem2);
vListInsert((List_t *)&TestList, (ListItem_t *)&ListItem3);
printf("\r\n");
printf("TestList信息更新\r\n");
printf("TestList\t\t0x%p\t\r\n", &TestList);
printf("TestList->pxIndex\t0x%p\t\r\n", TestList.pxIndex);
printf("TestList->xListEnd\t0x%p\t\r\n", (&TestList.xListEnd));
printf("TestList->uxNumberOfItems\t%ld\t\r\n", TestList.uxNumberOfItems);
TestList.pxIndex = TestList.xListEnd.pxPrevious;
printf("倒数第二个列表项\t0x%p\t\r\n", (TestList.pxIndex));
TestList.pxIndex = TestList.pxIndex->pxPrevious;
printf("倒数第三个列表项\t0x%p\t\r\n", (TestList.pxIndex));
TestList.pxIndex = TestList.pxIndex->pxPrevious;
printf("倒数第四个列表项\t0x%p\t\r\n", (TestList.pxIndex));
printf("\r\n");
printf("在TestList列表中插入列表项1,2,3,xItemValue的值为3,2,1\r\n");
ListItem1.xItemValue = 3;
ListItem2.xItemValue = 2;
ListItem3.xItemValue = 1;
vListInsert((List_t *)&TestList, (ListItem_t *)&ListItem1);
vListInsert((List_t *)&TestList, (ListItem_t *)&ListItem2);
vListInsert((List_t *)&TestList, (ListItem_t *)&ListItem3);
printf("\r\n");
printf("TestList信息更新\r\n");
printf("TestList\t\t0x%p\t\r\n", &TestList);
printf("TestList->pxIndex\t0x%p\t\r\n", TestList.pxIndex);
printf("TestList->xListEnd\t0x%p\t\r\n", (&TestList.xListEnd));
printf("TestList->uxNumberOfItems\t%ld\t\r\n", TestList.uxNumberOfItems);
TestList.pxIndex = TestList.xListEnd.pxPrevious;
printf("倒数第二个列表项\t0x%p\t\r\n", (TestList.pxIndex));
TestList.pxIndex = TestList.pxIndex->pxPrevious;
printf("倒数第三个列表项\t0x%p\t\r\n", (TestList.pxIndex));
TestList.pxIndex = TestList.pxIndex->pxPrevious;
printf("倒数第四个列表项\t0x%p\t\r\n", (TestList.pxIndex));
printf("\r\n");
printf("在TestList列表移除列表项2\r\n");
uxListRemove((ListItem_t *)&ListItem2);
printf("\r\n");
printf("TestList信息更新\r\n");
printf("TestList\t\t0x%p\t\r\n", &TestList);
printf("TestList->pxIndex\t0x%p\t\r\n", TestList.pxIndex);
printf("TestList->xListEnd\t0x%p\t\r\n", (&TestList.xListEnd));
printf("TestList->uxNumberOfItems\t%ld\t\r\n", TestList.uxNumberOfItems);
TestList.pxIndex = TestList.xListEnd.pxPrevious;
printf("倒数第二个列表项\t0x%p\t\r\n", (TestList.pxIndex));
TestList.pxIndex = TestList.pxIndex->pxPrevious;
printf("倒数第三个列表项\t0x%p\t\r\n", (TestList.pxIndex));
TestList.pxIndex = TestList.pxIndex->pxPrevious;
printf("倒数第四个列表项\t0x%p\t\r\n", (TestList.pxIndex));
printf("\r\n");
printf("在TestList列表中末尾插入列表项2\r\n");
vListInsertEnd((List_t *)&TestList, (ListItem_t *)&ListItem2);
printf("\r\n");
printf("TestList信息更新\r\n");
printf("TestList\t\t0x%p\t\r\n", &TestList);
printf("TestList->pxIndex\t0x%p\t\r\n", TestList.pxIndex);
printf("TestList->xListEnd\t0x%p\t\r\n", (&TestList.xListEnd));
printf("TestList->uxNumberOfItems\t%ld\t\r\n", TestList.uxNumberOfItems);
TestList.pxIndex = TestList.xListEnd.pxPrevious;
printf("倒数第二个列表项\t0x%p\t\r\n", (TestList.pxIndex));
TestList.pxIndex = TestList.pxIndex->pxPrevious;
printf("倒数第三个列表项\t0x%p\t\r\n", (TestList.pxIndex));
TestList.pxIndex = TestList.pxIndex->pxPrevious;
printf("倒数第四个列表项\t0x%p\t\r\n", (TestList.pxIndex));
while(1)
{
vTaskDelay(1000);
}
}
实际运行示例: