任务堆栈

vTaskList 介绍

可通过 vTaskList() 来协助分析操作系统当前 task 状态,以帮助优化内存,帮助定位栈溢出问题,帮助理解和学习操作系统原理相关知识。

vTaskList 使用

使用 vTaskList() 前需使能:

  • make menuconfig -> Component config -> FreeRTOS -> Enable FreeRTOS trace facility
  • make menuconfig -> Component config -> FreeRTOS -> Enable FreeRTOS trace facility -> Enable FreeRTOS stats formatting functions

通过上面配置,等同于使能 FreeRTOSConfig.h 中如下两个宏:
configUSE_TRACE_FACILITYconfigUSE_STATS_FORMATTING_FUNCTIONS

1
2
3
4
5
6
void SystemInfo::PrintTaskList() {
char buffer[1024];
vTaskList(buffer);
printf("任务名 任务状态 优先级 剩余栈 任务序号 cpu核\r\n");
printf("%s", buffer);
}

vTaskList 结果

1
2
3
4
5
6
7
8
9
10
11
12
13
任务名  任务状态  优先级  剩余栈  任务序号  cpu核
touch_task R 5 1260 25 1
audio_loop B 8 6624 14 -1
taskLVGL B 22 2460 12 -1
motion_detectio B 5 804 26 -1
LoactionService B 5 3884 21 -1
LoactionService B 5 3880 20 -1
mqtt_task B 5 4596 18 -1
animation task B 7 3176 22 -1
PointAnimTask B 6 2336 24 -1
animation task B 8 1252 23 -1
main B 3 4576 4 0
background_task B 2 2500 9 -1
  • 第一列: 任务名
    xTaskCreate 创建该 task 时的第二个参数。如果名称过长,会根据 configMAX_TASK_NAME_LEN 截断。

  • 第二列: task 当前状态

    • X: running:运行态
    • B: blocked:阻塞态
    • R: ready:就绪态
    • D: deleted:结束态
    • S: suspended:挂起态
  • 第三列: task 优先级
    xTaskCreate 创建该 task 时的第四个参数。

  • 第四列: 最小剩余 task 栈空间,字节为单位
    xTaskCreate 创建 task 时,给定的第三个参数值代表该 task 调度和运行过程中,最大可用 task 栈空间,以字节为单位(可以修改 portSTACK_TYPE 宏来决定是否以字节还是 4 字节为单位);
    Task 如果 API 调用比较深,则使用的栈空间越大,也就意味着最小剩余 task 栈空间越小。

  • 第五列:task 创建顺序

  • 第六列:CPU 核心

    • 绑定特定核心(如 0 和 1):当任务被绑定到某个特定核心(例如 main 任务在核心 0 上,touch_task 在核心 1 上),意味 RTOS 会尝试让这个任务只在指定的核心上执行。
    • 不绑定核心(值为-1):对于 cpu 列显示为 -1 的任务(如 audio_loop, taskLVGL 等),操作系统可以将其调度到当前空闲的任何逻辑核心上执行。这给予了操作系统调度器最大的灵活性,以便在有多核的情况下平衡负载。

注意

  • 当某个 task 最小剩余 task 栈空间比较大时,适当减小 xTaskCreate 创建该 task 时给定的第三个参数值,可节约 DRAM,以优化系统内存
  • 当某个 task 最小剩余 task 栈空间比较小时,适当增大 xTaskCreate 创建该 task 时给定的第三个参数值,可降低 task 栈溢出风险
  • 减少应用代码 task 的个数,以优化内存。
  • 占用空间较大的变量,尽可能通过 malloc/calloc 等动态申请释放,以提高栈空间利用率。