FreeRTOS#3——列表与列表项
·
列表和列表项
FreeRTOS中使用 双向循环链表 表示列表 用来跟踪任务
一个任务有两个 列表项(事件列表项、状态列表项),列表项通过指针指向任务的TCB,当任务的状态列表项挂在在哪个列表中(就绪、阻塞、挂起)这个任务就处于那种状态
- 事件列表项
- 任务在等什么
- 队列、信号量、互斥量、事件组、流缓冲区和消息缓冲区的等待列表 和 直接任务通知的等待
- 有相应事件触发后,内核去对应事件的等待列表中查找哪个任务在等待该事件,不需要便利所有阻塞的任务
- 状态列表项
- 任务什么时候能运行
- 就绪、阻塞、挂起列表,这些列表在全局中定义好的,任务创建时加入某一个列表

列表项
typedef struct xLIST_ITEM ListItem_t;
typedef struct xMINI_LIST_ITEM MiniListItem_t;
typedef struct xLIST
{
listFIRST_LIST_INTEGRITY_CHECK_VALUE //校验值
volatile UBaseType_t uxNumberOfItems; //列表中列表项个数
ListItem_t * configLIST_VOLATILE pxIndex; //用于遍历列表的指针
MiniListItem_t xListEnd; //末尾列表项 //循环列表,找到末尾 +1即使列表头
listSECOND_LIST_INTEGRITY_CHECK_VALUE //校验值
} List_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;
}; //用于标记列表末尾 和 挂在其他插入列表中的 列表项
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; //列表项的拥有者,指向该任务的PTB
struct xLIST * configLIST_VOLATILE pxContainer; //列表项所在列表,阻塞、就绪、挂起
listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE //校验值
};
列表API
- void vListInitialise( List_t * const pxList )
- 初始化列表
- void vListInitialiseItem( ListItem_t * const pxItem )
- 初始化列表项
- void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem )
- 列表升序插入列表项
- void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem )
- 列表末尾插入列表项,插到列表pxIndex指针所指列表项前面
- unsigned long uxListRemove( ListItem_t * const pxItemToRemove )
- 列表移除列表项
- 返回 列表剩余列表项数量
就绪列表
一个由 List_t 类型的变量组成的数组,数组大小为 configMAX_PRIORITIES。
PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ];
数组的每个索引,对应一个优先级,调度器需要寻找下一个要运行的任务时,它会 从最高优先级向最低优先级扫描这个数组,找到第一个非空的就绪列表,然后取出该列表头部的任务来运行。
阻塞列表
通常是两个有序的(升序)链表。
xDelayedTaskList1xDelayedTaskList2pxDelayedTaskList和pxOverflowDelayedTaskList这两个指针会指向上面两个列表,用于处理系统滴答计数器溢出的情况。
按 唤醒时间(Unblock Time) 排序。任务的 xWakeTime 值(即它应该被唤醒的时刻)被用作排序的关键字。
作用:
- 当一个任务调用
vTaskDelay()或等待一个带有超时时间的事件(如xQueueReceive(..., timeout))时,它会被从就绪列表中移除,并按其唤醒时间插入到阻塞列表中。塞入列表时会判断延时时间,决定塞入溢出前列表还是溢出后列表 - 每次 系统时钟滴答中断(Tick Interrupt) 发生时,中断服务程序都会检查阻塞列表的头项。如果某个任务的唤醒时间小于或等于当前时间,说明它应该被唤醒了,就会将其从阻塞列表移回就绪列表。
挂起列表
挂起是一种 由开发者主动发起 的任务状态,与等待事件无关
数据结构:一个简单的 List_t,xSuspendedTaskList。
组织方式:无序。所有被挂起的任务都放在这个列表里。
作用:
- 当一个任务调用
vTaskSuspend()时,无论它当前在什么状态(就绪、阻塞等),都会被强制移出原来的列表,并加入到挂起列表中。 - 被挂起的任务 永远不会被调度器选择运行,直到其他任务或中断调用
vTaskResume()将其恢复。恢复时,任务会根据其情况被放回就绪列表或阻塞列表。 vTaskSuspendAll()是一个不同的概念,它挂起的是调度器本身,而不是单个任务。
更多推荐

所有评论(0)