3. 任务管理与状态机:任务创建/删除/挂起/恢复、任务状态迁移、空闲任务与钩子函数
各位同学,咱们今天聊聊RTOS里最核心的东西——任务管理。说白了,就是操作系统怎么管好你那一堆并发跑着的任务。我做了这么多年嵌入式,见过太多因为任务管理不当导致系统崩溃的案例。嗯,咱们一个一个来看。
3.1 任务的生命周期:创建、删除、挂起与恢复
任务就像一个有生命的个体。它从出生到消亡,中间可能被暂停,也可能被唤醒。在RTOS里,我们通过几个API来操控它。
3.1.1 任务创建
创建任务,就是给系统注册一个可以独立运行的函数。我个人习惯用 xTaskCreate(),它是FreeRTOS里最常用的接口。你想想看,每个任务都需要自己的栈空间,这个栈大小很关键。
// 任务创建示例
TaskHandle_t xTaskHandle = NULL;
void vTaskFunction(void *pvParameters) {
while(1) {
// 任务主体
vTaskDelay(pdMS_TO_TICKS(100));
}
}
// 创建任务
xTaskCreate(
vTaskFunction, // 任务函数
"MyTask", // 任务名称(调试用)
1024, // 栈深度(单位:字)
NULL, // 参数
1, // 优先级
&xTaskHandle // 任务句柄
);
3.1.2 任务删除
任务跑完了,或者你不想让它跑了,就删掉它。用 vTaskDelete()。注意,删除任务时,系统会回收它的栈和TCB(任务控制块)。
// 删除任务自身
vTaskDelete(NULL);
// 删除指定任务
vTaskDelete(xTaskHandle);
3.1.3 任务挂起与恢复
挂起,就是让任务暂时休眠,不参与调度。恢复,就是把它唤醒。这两个操作在调试和低功耗场景里特别有用。
为什么会用到挂起?举个例子,你有一个周期性采集数据的任务,但系统进入低功耗模式时,你不想让它继续跑。这时候挂起它,等唤醒后再恢复。
// 挂起任务
vTaskSuspend(xTaskHandle);
// 恢复任务
vTaskResume(xTaskHandle);
3.2 任务状态迁移
任务在RTOS里,有四种基本状态:运行态、就绪态、阻塞态、挂起态。它们之间的迁移,是调度器工作的基础。
| 当前状态 | 触发事件 | 迁移到状态 |
|---|---|---|
| 运行态 | 时间片用完 | 就绪态 |
| 运行态 | 等待信号量/队列 | 阻塞态 |
| 运行态 | 调用vTaskSuspend | 挂起态 |
| 阻塞态 | 等待条件满足 | 就绪态 |
| 挂起态 | 调用vTaskResume | 就绪态 |
我记得有一次调试自动驾驶的决策模块,发现一个任务老是卡住。查了半天,原来是它一直在阻塞态等一个永远不会来的信号量。说白了,就是状态机卡死了。从那以后,我养成了一个习惯:每个阻塞调用都加超时。
3.3 空闲任务与钩子函数
空闲任务,是RTOS里最低优先级的任务。当没有其他任务可以运行时,系统就跑去跑空闲任务。它主要做两件事:释放被删除任务的资源,以及调用钩子函数。
3.3.1 空闲任务的作用
你想想看,如果所有任务都阻塞了,CPU总不能空转吧?空闲任务就是干这个的。它负责清理那些被删除任务的残留资源,比如栈和TCB。
在自动驾驶系统里,空闲任务特别重要。因为传感器数据采集任务、控制任务、通信任务,它们可能同时阻塞等待。这时候空闲任务可以进入低功耗模式,省电。
3.3.2 钩子函数
钩子函数,说白了就是空闲任务里可以插入的一个自定义函数。你可以在里面做低功耗处理、CPU利用率统计、或者系统健康检查。
// 启用空闲任务钩子
// 在FreeRTOSConfig.h中设置
#define configUSE_IDLE_HOOK 1
// 实现钩子函数
void vApplicationIdleHook(void) {
// 进入低功耗模式
__WFI(); // Wait For Interrupt
// 或者统计CPU利用率
static uint32_t ulIdleCount = 0;
ulIdleCount++;
}
3.3.3 钩子函数的注意事项
嗯,这里要注意。钩子函数里不能调用任何可能导致任务阻塞的API。比如 vTaskDelay()、xQueueReceive() 这些都不能用。为什么?因为空闲任务本身就不能被阻塞,否则系统就崩了。
我曾经见过一个同事,在钩子函数里调用了 vTaskDelay(10),结果系统直接死机。排查了半天,才发现是这个问题。所以,钩子函数里只做轻量级操作,比如读个寄存器、喂个狗、统计个计数。
好了,这一章的内容就到这里。下一章咱们聊聊任务间通信,信号量和队列。那才是真正让任务协同工作的关键。