FreeRTOS記憶體管理原始碼分析

2021-10-06 07:25:35 字數 3625 閱讀 3396

記憶體管理一直都是重中之重的知識。記憶體管理在freertos系統中是可裁剪可配置的。freertos提供了5種記憶體管理方案。暫時可能分析不完5種方案,今天能寫多少先寫多少,後續有時間了再一點一點的寫吧。5中方案對比如下:

方案1:記憶體一旦分配出去就無法**了。記憶體釋放函式是乙個空函式,什麼都沒做。

方案2:可以分配記憶體也可以釋放記憶體。缺點就是可能會造成記憶體碎片。釋放回去的記憶體不會合併成大塊記憶體。

方案3:和標準c的malloc函式free函式一樣,唯一的區別就是對標準c庫的記憶體管理函式做了乙個執行緒安全保護。

方案4:在方案2的基礎上實現了小記憶體塊合併成大記憶體塊的功能。可以分配記憶體釋放記憶體,也可以合併記憶體碎片。

方案5:前邊的4種記憶體管理方案中,記憶體堆空間只能在乙個連續的物理空間中,要麼mcu內部ram,要麼外部sram,要不外部sdram,總之只能選擇其一。而方案5則可以把堆空間分布到不連續的物理空間中。這樣的話使用起來就更靈活更自由了(原諒我這一生**不羈愛自由)。

哦。差點忘了說為什麼不用普通的標準c的記憶體管理方案。原因有以下幾點:

在小型的嵌入式系統中效率低。

標準c的記憶體管理會占用大量的**空間。

不是執行緒安全的。

具體不確定性,每次執行的時間都不同。

會導致記憶體碎片。

是聯結器的配置變的複雜。

廢話說完了,我們先來看方案1吧。

方案1的記憶體申請函式如下

void

*pvportmalloc

( size_t xwantedsize )

}#endif

vtasksuspendall()

;//對記憶體申請過程做了乙個安全保護

/* check there is enough room left for the allocation. */if(

(( xnextfreebyte + xwantedsize )

< configadjusted_heap_size )

&&//判斷剩餘的記憶體空間是否充足

(( xnextfreebyte + xwantedsize )

> xnextfreebyte )

)/* check for overflow. */

//防止申請的記憶體空間溢位

tracemalloc

( pvreturn, xwantedsize );}

(void

)xtaskresumeall()

;#if( configuse_malloc_failed_hook == 1 )

}#endif

return pvreturn;

}

1、#if( portbyte_alignment != 1 )條件編譯 是否按指定的位元組對齊,有1,2,4,8,16,32位元組對齊。比如8位元組對齊(我們接下來預設以8位元組對齊來討論)。

2、if( xwantedsize & portbyte_alignment_mask )如果條件為真那麼xwantedsize一定不是8的倍數。如果不是8的倍數就補到8的倍數。

**xwantedsize += ( portbyte_alignment - ( xwantedsize & portbyte_alignment_mask ) );將申請的位元組數補到8的倍數。

3、vtasksuspendall();掛起任務排程器。這樣做就是為了實現可重入。

系統第一次呼叫記憶體申請函式,對堆記憶體的起始位址做位元組對齊。

pucalignedheap = ( uint8_t * ) ( ( ( portpointer_size_type ) &ucheap[ portbyte_alignment ] ) & ( ~( ( portpointer_size_type ) portbyte_alignment_mask ) ) );

如果是我們自己發揮思維怎麼寫?挨個找嗎?官方是通過位元組對齊的掩碼算出來的,效率極高。不知到大家有沒有看出,這行**有個小小的問題,。下面我們舉例來詳細剖析這個問題。

假設這樣一種情況:堆記憶體的起始位址恰好是8位元組對齊的,使用者選擇8位元組對齊。

&ucheap[ portbyte_alignment ]就相當於&ucheap[ 8 ]

通過pucalignedheap = ( uint8_t * ) ( ( ( portpointer_size_type ) &ucheap[ portbyte_alignment ] ) & ( ~( ( portpointer_size_type ) portbyte_alignment_mask ) ) );算出來的就是ucheap[ 8 ]的位址。大家可以用乙個8位元組的位址帶進去算一下,

現在的情況是這樣的:記憶體起始位址恰好是8位元組對齊的,那麼也就是ucheap[ 0]的位址就是8位元組對齊的,而計算出來卻得到了ucheap[ 8 ]的位址,這樣前邊就浪費了8個位元組。這個問題無傷大雅,有12.5%的概率會浪費8位元組空間。

我曾在freertos官方論壇發帖反映過,freertos作者測試後也認可我反饋餓問題。

if((

( xnextfreebyte + xwantedsize )

< configadjusted_heap_size )

&&//判斷剩餘的記憶體空間是否充足

(( xnextfreebyte + xwantedsize )

> xnextfreebyte )

)/* check for overflow. */

//防止申請的記憶體空間溢位

我們需要明確xnextfreebytexwantedsize的意義。

xnextfreebyte已分配出去的位元組數。

xwantedsize本次需要分配出去的位元組數。

申請記憶體需要滿足兩個條件,第一堆中有足夠的剩餘記憶體,第二xnextfreebyte沒有溢位

pvreturn = pucalignedheap + xnextfreebyte;//計算出實際的實體地址

xnextfreebyte += xwantedsize;//記錄已經分配出去的位元組數

條件編譯#if( configuse_malloc_failed_hook == 1 )是當記憶體申請失敗的時候呼叫乙個鉤子函式。

最後返回申請到記憶體的位址。

釋放記憶體函式

void

vportfree

(void

*pv )

可以看出釋放記憶體是乙個空函式,函式內部只有乙個斷言。當使用方案1的釋放函式時會強制乙個斷言錯誤。

獲取剩餘記憶體函式

size_t xportgetfreeheapsize

(void

)

方案1的分析到此為止。

FreeRTOS 記憶體管理

1.標準malloc 和 free 庫函式的缺陷 1 在小型的嵌入式系統中,可能不可用。2 具體實現相對較大,占用較多寶貴的 空間。3 通常不具備執行緒安全性。4 具有不確定性,每次呼叫的時間開銷可能不同。5 會產生記憶體碎片。6 會使得鏈結器 配置的複雜。2.記憶體分配方案範例。1 heap 1....

FreeRTOS原始碼閱讀 一

之前閱讀了rt thread 的原始碼,rtt原始碼是unix風格,看起來比較熟悉.最近有些空閒時間,打算閱讀freertos的原始碼,看看兩者的差別。freertos作業系統是完全免費的作業系統,具有原始碼公開 可移植 可裁減 排程策略靈活的特點,可以方便地移植到各種微控制器上執行 來自度娘 如今...

FreeRTOS初探 記憶體管理

記憶體管理 概覽 背景 每當任務 佇列或是訊號量被建立時,核心需要進行動態記憶體分配。呼叫標準的malloc 和free 庫函式,必須承擔以下若干問題 解決方案 freertos將記憶體分配作為可移植層面。內容 記憶體分配方案範例 heap 1.c heap 1.c實現乙個非常基本的pvportma...