(八)FreeRTOS記憶體管理

2021-10-11 00:24:39 字數 2881 閱讀 9222

本文介紹記憶體管理的基礎知識,詳細原始碼分析見《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時,這個記憶體分配方案只是簡單的將乙個大陣列細分出乙個子集來。...