FreeRTOS 接口: vTaskList() - 可優化內存和 task 棧溢出定位

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_FACILITYconfigUSE_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: running
    • B: blocked
    • R: ready
    • D: deleted
    • S: 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 創建順序

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章