FreeRTOS 提供了多種動態內存分配方案,這些方案通過不同的內存管理器(heap managers)實現,主要位于 FreeRTOS/Source/portable/MemMang
目錄下。以下是幾種常見的動態內存分配方案:
heap_1
特點:
- 簡單性:
heap_1
是所有FreeRTOS內存管理方案中最簡單的一個。它的設計目標是在資源受限的嵌入式系統中提供基本的動態內存分配功能。 - 不可釋放內存:與其他幾種內存管理方案不同,
heap_1
分配出去的內存空間一旦分配完成,就不支持再次釋放。這意味著一旦任務、信號量、消息隊列等分配了內存,這部分內存將永久占用,直到系統重啟。 - 單塊分配:它維護一個連續的內存塊,當有內存分配請求時,直接從這個內存塊中切割出所需大小的空間。這種方式不涉及復雜的內存碎片管理。
- 低開銷:因為其簡單的設計,
heap_1
的運行時開銷相對較小,適合那些對內存管理開銷非常敏感的應用場景。
工作原理:
- 初始化:在系統啟動時,
heap_1
會初始化一個大的靜態內存數組(通常稱為 ucHeap[]),這個數組構成了整個可分配內存的池。 - 分配過程:當任務需要內存時,
heap_1
會檢查 ucHeap[] 中是否有足夠大的連續空間來滿足請求。如果有,它就從這片連續空間中分配出所需的內存,并更新剩余內存的記錄。 - 無釋放操作:一旦分配,
heap_1
不支持通過函數調用來釋放已分配的內存。這意呀著開發者必須謹慎地規劃內存的使用,避免不必要的分配,以免過早耗盡內存資源。
使用場景:
由于 heap_1
的特性,它最適合那些對內存管理要求不高、內存分配模式可預測、且不需要頻繁釋放內存的應用。例如,某些簡單的嵌入式系統、原型開發或對實時性要求極高而對內存靈活性要求較低的場合。
heap_2
特點:
- 多尺寸管理:
heap_2
引入了對不同尺寸內存塊的管理。它將可用內存分割成多個鏈表,每個鏈表負責管理特定大小的內存塊。這有助于減少內存碎片,提高內存分配和回收的效率。 - 支持內存釋放:與
heap_1
不同,heap_2
支持動態地分配和釋放內存。當任務不再需要一塊內存時,可以通過調用釋放函數將內存歸還給相應的鏈表,使得這塊內存可以被后續的分配請求重復利用。 - 減少碎片:通過將內存按大小分類管理,
heap_2
可以更有效地復用內存塊,減少因頻繁分配和釋放不同大小內存而產生的碎片問題。
工作原理:
- 初始化:初始化時,
heap_2
會將整個內存池分割成多個預定義大小的內存塊,并將這些塊分別鏈接到對應的鏈表中。 - 分配過程:當有內存分配請求時,
heap_2
會遍歷鏈表,尋找第一個足夠大的內存塊。如果找到,該塊將從鏈表中移除并返回給請求者。如果找不到合適大小的塊,且系統配置允許,可能會從更大的塊中分割出所需大小的塊,然后將剩余部分放回相應鏈表。 - 釋放過程:釋放內存時,該內存塊會根據其大小被放回到正確的鏈表中。這樣,相同大小的塊可以被高效復用。
使用場景:
heap_2
適用于那些需要動態分配和釋放內存、并且對內存使用效率有一定要求的嵌入式系統。它特別適合于存在多種不同大小內存需求的應用場景,通過減少內存碎片,提高了內存利用率,降低了內存分配失敗的風險。然而,相較于 heap_1
,heap_2
的管理邏輯更為復雜,可能帶來一定的運行時開銷。因此,在選擇是否使用 heap_2
時,需要權衡系統對內存管理靈活性和效率的需求與額外開銷之間的關系。
heap_3
特點:
- 依賴宿主環境:與 FreeRTOS 內置的其他內存管理方案不同,
heap_3
不直接管理內存,而是調用 C 標準庫的內存管理函數。這意味著它依賴于編譯器或宿主機操作系統提供的內存管理實現。 - 簡單集成:由于直接利用現有的內存管理接口,
heap_3
的集成相對簡單,無需深入了解復雜的內存分配算法或數據結構。 - 功能全面:因為使用標準庫的
malloc()
和free()
,理論上支持任意大小的內存塊分配和釋放,具有很高的靈活性。
使用考量:
- 性能和開銷:雖然使用方便,但
heap_3
的性能和開銷取決于宿主環境的內存管理實現。在一些資源受限的嵌入式系統中,標準庫的內存管理可能不夠高效,引入額外的開銷或延遲。 - 兼容性和移植性:由于依賴于外部內存管理函數,
heap_3
的行為可能隨編譯器或平臺的不同而有所變化,影響系統的兼容性和移植性。 - 實時性:標準庫的內存管理函數往往不是為硬實時系統設計的,可能無法保證嚴格的時序要求,這對于某些對時間敏感的嵌入式應用可能不適宜。
適用場景:
- 對于快速原型開發或評估階段,開發者可能優先考慮使用
heap_3
,因為它簡化了內存管理的實現,便于快速測試其他系統功能。 - 當項目運行在擁有高效內存管理機制的宿主環境,且實時性要求不高時,
heap_3
也是一個可行的選擇。 - 對于需要與宿主系統(如桌面操作系統上的模擬器或測試環境)緊密集成的開發場景,使用
heap_3
可以減少自定義內存管理代碼的工作量。
Heap_4
是 FreeRTOS 提供的動態內存分配方案之一。FreeRTOS 支持多種內存分配策略,以適應不同應用場景的需求, Heap_4 是這些策略中的一種實現。下面簡要介紹 Heap_4 的特點和工作原理:
Heap_4
特點:
-
簡單高效:Heap_4 實現相對簡單,它通過維護一個或多個內存塊鏈表來管理可用的內存空間。這些內存塊按照大小排序,當有新的內存分配請求時,它會從鏈表中尋找最合適的塊進行分配。
-
固定塊大小分配:與 Heap_1、Heap_2 和 Heap_3 不同,Heap_4 并不直接支持任意大小的內存分配請求。它更適合于那些內存需求較為固定、或者可以預先確定幾種常見大小的情況。開發者需要預先定義好幾種不同大小的內存塊池,每個池維護一個鏈表。
-
減少碎片:通過限制分配的內存塊大小種類,Heap_4 有助于減少內存碎片問題。特別是在那些頻繁分配和釋放固定大小對象的應用場景中,能夠更有效地復用內存塊,避免小碎片積累導致的大塊內存無法分配的問題。
-
配置靈活性:用戶可以根據應用的具體需求,配置不同的內存塊大小和數量,以達到最佳的內存使用效率和性能平衡。
工作原理:
- 初始化:在系統啟動時,Heap_4 會被初始化,此時會根據配置好的內存塊大小劃分整個可用的內存區域,為每個大小創建一個或多個內存塊鏈表。
- 分配內存:當任務需要分配內存時,Heap_4 會在對應大小的鏈表中查找是否有空閑的內存塊。如果有,則從中取出一個分配給請求者;如果沒有足夠大的塊,且配置允許,可能會嘗試分裂大塊以滿足請求,但這通常不在 Heap_4 的直接功能范圍內,更多依賴于如何預先配置內存池。
- 釋放內存:釋放內存時,該內存塊會被重新鏈接到對應大小的鏈表中,等待下一次分配使用。