vTaskList() 介紹
使用 ESP32
/ESP8266
進行開發時,讀者可通過 vTaskList()
來協助分析操作系統當前 task 狀態,以幫助優化內存,幫助定位棧溢出問題,幫助理解和學習操作系統原理相關知識。
讀者若想深入瞭解
vTaskList()
, 可參考 vTaskList() 英文原版介紹 相關文檔。
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_FACILITY
和configUSE_STATS_FORMATTING_FUNCTIONS
參考代碼
#include <stdio.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
void esp_print_tasks(void)
{
char *pbuffer = (char *)calloc(1, 2048);
printf("--------------- heap:%u ---------------------\r\n", esp_get_free_heap_size());
vTaskList(pbuffer);
printf("%s", pbuffer);
printf("----------------------------------------------\r\n");
free(pbuffer);
}
void test_task(void *param)
{
while(1) {
esp_print_tasks();
vTaskDelay(3000 / portTICK_RATE_MS);
}
}
打印一次 task 情況可調用:
esp_print_tasks();
循環打印 task 情況可調用:
xTaskCreate(test_task, "test_task", 2048, NULL, 5, NULL);
vTaskList() 結果和高能預警
讀者可以去
task.c
中查看vTaskList()
相關實現邏輯,或更有助於讀者理解。
例如: 基於 ESP8266, release/v3.3, commit:4c38ff31
, 在 app_main()
中調用 vTaskList()
結果如下:
-
第一列: task name
即xTaskCreate
創建該 task 時第二個參數。
如果名稱過長,會根據configMAX_TASK_NAME_LEN
截斷。 -
第二列: task 當前狀態
X
: runningB
: blockedR
: readyD
: deletedS
: suspended
-
第三列: task 優先級
即xTaskCreate
創建該 task 時第四個參數。
數字越大,優先級越高,建議客戶設置 task 優先級在 1-9 之間,慎行! -
第四列: 最小剩餘 task 棧空間,字節爲單位
在xTaskCreate
創建 task 時,給定的第三個參數值代表該 task 調度和運行過程中,最大可用 task 棧空間,以字節爲單位(讀者可以修改portSTACK_TYPE
宏來決定是否以字節還是4字節爲單位);
Task
如果 API 調用比較深,則使用的棧空間越大,也就意味着最小剩餘 task 棧空間越小。高能預警,做好筆記,熟讀三遍:
A:
當某個 task 最小剩餘 task 棧空間比較大時,適當減小xTaskCreate
創建該 task 時給定的第三個參數值,可節約 DRAM,以優化系統內存。B:
當某個 task 最小剩餘 task 棧空間比較小時,適當增大xTaskCreate
創建該 task 時給定的第三個參數值,可降低 task 棧溢出風險。C:
如果對 SDK 沒有深入瞭解,不要修改 系統 task 優先級和分配的最大可用棧空間。D:
減少應用代碼 task 的個數,以優化內存。
例如:
多個socket
數據流,可以通過select()
放在同一個 task 裏處理;
而不是一個socket
數據流,一個 task;
更不要一個socket
數據流,居然三個 task (接收 task, 發送 task, 處理 task), it is amazing!E:
佔用空間較大的變量,儘可能通過 malloc/calloc 等動態申請釋放,以提高棧空間利用率。 -
第五列: task 創建順序