您好,登錄后才能下訂單哦!
這篇“FreeRTOS實時操作系統的內存怎么管理”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“FreeRTOS實時操作系統的內存怎么管理”文章吧。
FreeRTOS提供了幾個內存堆管理方案,有復雜的也有簡單的。其中最簡單的管理策略也能滿足很多應用的要求,比如對安全要求高的應用,這些應用根本不允許動態內存分配的。
FreeRTOS也允許你自己實現內存堆管理,甚至允許你同時使用兩種內存堆管理方案。同時實現兩種內存堆允許任務堆棧和其它RTOS對象放置到快速的內部RAM,應用數據放置到低速的外部RAM。
每當創建任務、隊列、互斥量、軟件定時器、信號量或事件組時,RTOS內核會為它們分配RAM。標準函數庫中的malloc()和free()函數有些時候能夠用于完成這個任務,但是:
在嵌入式系統中,它們并不總是可以使用的;
它們會占用更多寶貴的代碼空間;
它們沒有線程保護;
它們不具有確定性(每次調用執行的時間可能會不同);
因此,提供一個替代的內存分配方案通常是必要的。
嵌入式/實時系統具有千差萬別的RAM和時間要求,因此一個RAM內存分配算法可能僅屬于一個應用的子集。
為了避免這個問題,FreeRTOS在移植層保留內存分配API函數。移植層在RTOS核心代碼源文件之外(不屬于核心源代碼),這使得不同的應用程序可以提供適合自己的應用實現。當RTOS內核需要RAM時,調用pvPortMallo()函數來代替malloc()函數。當RAM要被釋放時,調用vPortFree()函數來代替free()函數。
FreeRTOS下載包中提供5種簡單的內存分配實現,本文稍后會進行描述。用戶可以適當的選擇其中的一個,也可以自己設計內存分配策略。
FreeRTOS提供的內存分配方案分別位于不同的源文件(heap_1.c、heap_2.c、heap_3.c、heap_4.c、heap_5.c)之中,源文件位于下載包\FreeRTOS\Source\portable\MemMang文件夾中。其它實現方法可以根據需要增加。如果要使用FreeRTOS提供的內存堆分配方案,選中的源文件必須被正確的包含到工程文件中。
這是所有實現中最簡單的一個。一旦分配內存之后,它甚至不允許釋放分配的內存。盡管這樣,heap_1.c還是適用于大部分嵌入式應用程序。這是因為大多數深度嵌入式(deeplyembedded)應用只是在系統啟動時創建所有任務、隊列、信號量等,并且直到程序結束都會一直使用它們,永遠不需要刪除。
當需要分配RAM時,這個內存分配方案只是簡單的將一個大數組細分出一個子集來。大數組的容量大小通過FreeRTOSConfig.h文件中的configTOTAL_HEAP_SIZE宏來設置。
API函數xPortGetFreeHeapSize()返回未分配的堆棧空間總大小,可以通過這個函數返回值對configTOTAL_HEAP_SIZE進行合理的設置。
用于從不會刪除任務、隊列、信號量、互斥量等的應用程序(實際上大多數使用FreeRTOS的應用程序都符合這個條件)
執行時間是確定的并且不會產生內存碎片
實現和分配過程非常簡單,需要的內存是從一個靜態數組中分配的,意味著這種內存分配通常只是適用于那些不進行動態內存分配的應用。
和方案1不同,這個方案使用一個最佳匹配算法,它允許釋放之前分配的內存塊。它不會把相鄰的空閑塊合成一個更大的塊(換句話說,這會造成內存碎片)。
有效的堆棧空間大小由位于FreeRTOSConfig.h文件中的configTOTAL_HEAP_SIZE宏來定義。
API函數xPortGetFreeHeapSize()返回剩下的未分配堆棧空間的大小(可用于優化設置configTOTAL_HEAP_SIZE宏的值),但是不能提供未分配內存的碎片細節信息。
可以用于重復的分配和刪除具有相同堆棧空間的任務、隊列、信號量、互斥量等等,并且不考慮內存碎片的應用程序。
不能用在分配和釋放隨機字節堆棧空間的應用程序
如果一個應用程序動態的創建和刪除任務,并且分配給任務的堆棧空間總是同樣大小,那么大多數情況下heap_2.c是可以使用的。但是,如果分配給任務的堆棧不總是相等,那么釋放的有效內存可能碎片化,形成很多小的內存塊。最后會因為沒有足夠大的連續堆棧空間而造成內存分配失敗。在這種情況下,heap_4.c是一個很好的選擇。
如果一個應用程序動態的創建和刪除隊列,并且在每種情況下隊列存儲區域(隊列存儲區域指隊列項數目乘以每個隊列長度)都是同樣的,那么大多數情況下heap_2.c可以使用。但是,如果隊列存儲區在每種情況下并不總是相等,那么釋放的有效內存可能碎片化,形成很多小的內存塊。最后會因為沒有足夠大的連續堆棧空間而造成內存分配失敗。在這種情況下,heap_4.c是一個很好的選擇。
應用程序直接調用pvPortMalloc() 和 vPortFree()函數,而不僅是通過FreeRTOS API間接調用。
如果你的應用程序中的隊列、任務、信號量、互斥量等等處在一個不可預料的順序,則可能會導致內存碎片問題,雖然這是小概率事件,但必須牢記。
不具有確定性,但是它比標準庫中的malloc函數具有高得多的效率。
heap_2.c適用于需要動態創建任務的大多數小型實時系統(smallreal time)。
heap_3.c簡單的包裝了標準庫中的malloc()和free()函數,包裝后的malloc()和free()函數具備線程保護。
需要鏈接器設置一個堆棧,并且編譯器庫提供malloc()和free()函數。
不具有確定性
可能明顯的增大RTOS內核的代碼大小
注:使用heap_3時,FreeRTOSConfig.h文件中的configTOTAL_HEAP_SIZE宏定義沒有作用。
這個方案使用一個最佳匹配算法,但不像方案2那樣。它會將相鄰的空閑內存塊合并成一個更大的塊(包含一個合并算法)。
有效的堆棧空間大小由位于FreeRTOSConfig.h文件中的configTOTAL_HEAP_SIZE來定義。
API函數xPortGetFreeHeapSize()返回剩下的未分配堆棧空間的大小(可用于優化設置configTOTAL_HEAP_SIZE宏的值),但是不能提供未分配內存的碎片細節信息。
可用于重復分配、刪除任務、隊列、信號量、互斥量等等的應用程序。
可以用于分配和釋放隨機字節內存的情況,并不像heap_2.c那樣產生嚴重碎片。
不具有確定性,但是它比標準庫中的malloc函數具有高得多的效率。
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 { /* 用于內存堆的內存塊起始地址*/ uint8_t *pucStartAddress; /* 內存塊大小 */ size_t xSizeInBytes; } HeapRegion_t;
這個數組必須使用一個NULL指針和0字節元素作為結束,起始地址必須從小到大排列。下面的代碼段提供一個例子。MSVCWin32模擬器演示例程使用了heap_5,因此可以當做一個參考例程。
/* 在內存中為內存堆分配兩個內存塊.第一個內存塊0x10000字節,起始地址為0x80000000, 第二個內存塊0xa0000字節,起始地址為0x90000000.起始地址為0x80000000的內存塊的 起始地址更低,因此放到了數組的第一個位置.*/ const HeapRegion_t xHeapRegions[] = { { ( uint8_t * ) 0x80000000UL, 0x10000 }, { ( uint8_t * ) 0x90000000UL, 0xa0000 }, { NULL, 0 } /* 數組結尾. */ }; /* 向函數vPortDefineHeapRegions()傳遞數組參數. */ vPortDefineHeapRegions( xHeapRegions );
以上就是關于“FreeRTOS實時操作系統的內存怎么管理”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。