本文介紹記憶體管理的基礎知識,詳細原始碼分析見《freertos高階篇7---freertos記憶體管理分析》
freertos提供了幾個記憶體堆管理方案,有複雜的也有簡單的。其中最簡單的管理策略也能滿足很多應用的要求,比如對安全要求高的應用,這些應用根本不允許動態記憶體分配的。
freertos也允許你自己實現記憶體堆管理,甚至允許你同時使用兩種記憶體堆管理方案。同時實現兩種記憶體堆允許任務堆疊和其它rtos物件放置到快速的內部ram,應用資料放置到低速的外部ram。
每當建立任務、佇列、互斥量、軟體定時器、訊號量或事件組時,rtos核心會為它們分配ram。標準函式庫中的malloc()和free()函式有些時候能夠用於完成這個任務,但是:
在嵌入式系統中,它們並不總是可以使用的;
它們會占用更多寶貴的**空間;
它們沒有執行緒保護;
它們不具有確定性(每次呼叫執行的時間可能會不同);
因此,提供乙個替代的記憶體分配方案通常是必要的。
嵌入式/實時系統具有千差萬別的ram和時間要求,因此乙個ram記憶體分配演算法可能僅屬於乙個應用的子集。
為了避免這個問題,freertos在移植層保留記憶體分配api函式。移植層在rtos核心**原始檔之外(不屬於核心源**),這使得不同的應用程式可以提供適合自己的應用實現。當rtos核心需要ram時,呼叫pvportmallo()函式來代替malloc()函式。當ram要被釋放時,呼叫vportfree()函式來代替free()函式。
這是所有實現中最簡單的乙個。一旦分配記憶體之後,它甚至不允許釋放分配的記憶體。儘管這樣,heap_1.c還是適用於大部分嵌入式應用程式。這是因為大多數深度嵌入式(deeplyembedded)應用只是在系統啟動時建立所有任務、佇列、訊號量等,並且直到程式結束都會一直使用它們,永遠不需要刪除。
當需要分配ram時,這個記憶體分配方案只是簡單的將乙個大陣列細分出乙個子集來。大陣列的容量大小通過freertosconfig.**件中的configtotal_heap_size巨集來設定。
api函式xportgetfreeheapsize()返回未分配的堆疊空間總大小,可以通過這個函式返回值對configtotal_heap_size進行合理的設定。
heap_1功能簡介:
和方案1不同,這個方案使用乙個最佳匹配演算法,它允許釋放之前分配的記憶體塊。它不會把相鄰的空閒塊合成乙個更大的塊(換句話說,這會造成記憶體碎片)。
有效的堆疊空間大小由位於freertosconfig.**件中的configtotal_heap_size巨集來定義。
api函式xportgetfreeheapsize()返回剩下的未分配堆疊空間的大小(可用於優化設定configtotal_heap_size巨集的值),但是不能提供未分配記憶體的碎片細節資訊。
heap_2功能簡介:
如果你的應用程式中的佇列、任務、訊號量、互斥量等等處在乙個不可預料的順序,則可能會導致記憶體碎片問題,雖然這是小概率事件,但必須牢記。
不具有確定性,但是它比標準庫中的malloc函式具有高得多的效率。
heap_2.c適用於需要動態建立任務的大多數小型實時系統(smallreal time)。
heap_3.c簡單的包裝了標準庫中的malloc()和free()函式,包裝後的malloc()和free()函式具備執行緒保護。
heap_3.c功能簡介:
注:使用heap_3時,freertosconfig.**件中的configtotal_heap_size巨集定義沒有作用。
這個方案使用乙個最佳匹配演算法,但不像方案2那樣。它會將相鄰的空閒記憶體塊合併成乙個更大的塊(包含乙個合併演算法)。
有效的堆疊空間大小由位於freertosconfig.**件中的configtotal_heap_size來定義。
api函式xportgetfreeheapsize()返回剩下的未分配堆疊空間的大小(可用於優化設定configtotal_heap_size巨集的值),但是不能提供未分配記憶體的碎片細節資訊。
heap_4.c功能簡介:
heap_4.c還特別適用於移植層**,可以直接使用pvportmalloc()和 vportfree()函式來分配和釋放記憶體。
這個方案同樣實現了heap_4.c中的合併演算法,並且允許堆疊跨越多個非連續的記憶體區。
heap_5通過呼叫vportdefineheapregions()函式實現初始化,在該函式執行完成前不允許使用記憶體分配和釋放。建立rtos物件(任務、佇列、訊號量等等)會隱含的呼叫pvportmalloc(),因此必須注意:使用heap_5建立任何物件前,要先執行vportdefineheapregions()函式。
vportdefineheapregions()函式只需要單個引數。該引數是乙個
heapregion_t結構體型別陣列。heapregion_t在portable.h中定義,如下所示:
typedef struct heapregion
heapregion_t;
/* 在記憶體中為記憶體堆分配兩個記憶體塊.第乙個記憶體塊0x10000位元組,起始位址為0x80000000,
第二個記憶體塊0xa0000位元組,起始位址為0x90000000.起始位址為0x80000000的記憶體塊的
起始位址更低,因此放到了陣列的第乙個位置.*/
const heapregion_t xheapregions =
,
,
/* 陣列結尾. */
};
/* 向函式vportdefineheapregions()傳遞陣列引數. */
vportdefineheapregions( xheapregions );
FreeRTOS 記憶體管理
1.標準malloc 和 free 庫函式的缺陷 1 在小型的嵌入式系統中,可能不可用。2 具體實現相對較大,占用較多寶貴的 空間。3 通常不具備執行緒安全性。4 具有不確定性,每次呼叫的時間開銷可能不同。5 會產生記憶體碎片。6 會使得鏈結器 配置的複雜。2.記憶體分配方案範例。1 heap 1....
FreeRTOS初探 記憶體管理
記憶體管理 概覽 背景 每當任務 佇列或是訊號量被建立時,核心需要進行動態記憶體分配。呼叫標準的malloc 和free 庫函式,必須承擔以下若干問題 解決方案 freertos將記憶體分配作為可移植層面。內容 記憶體分配方案範例 heap 1.c heap 1.c實現乙個非常基本的pvportma...
FreeRTOS 1 記憶體管理
freertos提供的記憶體分配方案分別位於不同的原始檔 heap 1.c heap 2.c heap 3.c heap 4.c heap 5.c 之中 所有實現中最簡單的乙個。一旦分配記憶體之後,不允許釋放分配的記憶體。當需要分配ram時,這個記憶體分配方案只是簡單的將乙個大陣列細分出乙個子集來。...