引言
任务状态机是FreeRTOS调度器的核心,它定义了任务在不同时刻的状态以及状态之间的转换规则。理解任务状态机对于掌握FreeRTOS的调度机制至关重要。本文将深入分析FreeRTOS V11.1.0中任务状态的定义、转换机制和实现细节。
1. 任务状态定义
FreeRTOS定义了以下几种任务状态:
/* 任务状态枚举 */
typedef enum
{
eRunning = 0, /* 运行状态:任务正在执行 */
eReady, /* 就绪状态:任务准备运行,等待调度器分配CPU */
eBlocked, /* 阻塞状态:任务等待某个事件或资源 */
eSuspended, /* 挂起状态:任务被显式挂起,不参与调度 */
eDeleted, /* 删除状态:任务已被删除,TCB等待清理 */
eInvalid /* 无效状态:用于错误检查 */
} eTaskState;
2. 任务状态机架构
2.1 状态转换图
创建 ↓ ┌─────────┐ 调度器选中 ┌─────────┐ │ Ready │ ──────────────→ │ Running │ │ (就绪) │ ←────────────── │ (运行) │ └─────────┘ 时间片到期 └─────────┘ ↑ 或被抢占 │ │ │ 事件发生 等待事件 资源可用 或资源 │ │ │ ↓ ┌─────────┐ ┌─────────┐ │ Blocked │ │Suspended│ │ (阻塞) │ │ (挂起) │ └─────────┘ └─────────┘ │ │ └──────── 删除任务 ──────────┘ ↓ ┌─────────┐ │ Deleted │ │ (删除) │ └─────────┘
2.2 状态链表组织
FreeRTOS使用不同的链表来管理处于不同状态的任务:
/* 就绪任务链表数组 - 每个优先级一个链表 */
PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ];
/* 延时任务链表 */
PRIVILEGED_DATA static List_t xDelayedTaskList1;
PRIVILEGED_DATA static List_t xDelayedTaskList2;
PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList;
PRIVILEGED_DATA static List_t * volatile pxOverflowDelayedTaskList;
/* 挂起任务链表 */
#if ( INCLUDE_vTaskSuspend == 1 )
PRIVILEGED_DATA static List_t xSuspendedTaskList;
#endif
/* 等待删除的任务链表 */
#if ( INCLUDE_vTaskDelete == 1 )
PRIVILEGED_DATA static List_t xTasksWaitingTermination;
#endif
```## 3. 状
态转换机制详解
### 3.1 Ready → Running 转换
当调度器选择一个就绪任务运行时发生此转换:
```c
/* 任务选择宏 - 单核版本 */
#define taskSELECT_HIGHEST_PRIORITY_TASK() \
do { \
UBaseType_t uxTopPriority = uxTopReadyPriority; \
\
/* 找到包含就绪任务的最高优先级队列 */ \
while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopPriority ] ) ) != pdFALSE ) \
{ \
configASSERT( uxTopPriority ); \
--uxTopPriority; \
} \
\
/* 轮转选择同优先级任务 */ \
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \
uxTopReadyPriority = uxTopPriority; \
} while( 0 )
/* 实际的任务切换函数 */
void vTaskSwitchContext( void )
{
if( uxSchedulerSuspended != ( UBaseType_t ) pdFALSE )
{
/* 调度器被挂起,记录需要切换的标志 */
xYieldPendings[ portGET_CORE_ID() ] = pdTRUE;
}
else
{
xYieldPendings[ portGET_CORE_ID() ] = pdFALSE;
/* 选择下一个要运行的任务 */
taskSELECT_HIGHEST_PRIORITY_TASK();
/* 更新任务运行状态 */
#if ( configNUMBER_OF_CORES > 1 )
{
if( pxCurrentTCB != NULL )
{
pxCurrentTCB->xTaskRunState = portGET_CORE_ID();
}
}
#endif
}
}
3.2 Running → Ready 转换
任务从运行状态转为就绪状态的几种情况:
3.2.1 时间片到期
/* 在Ti

最低0.47元/天 解锁文章
1101

被折叠的 条评论
为什么被折叠?



