嵌入式裸機內存動態管理的實現與講解(一)

  • C 的標準庫自帶了mallocfree,爲啥還要自己實現?標準庫的函數佔用空間較大,採用本文的實現可節約幾KB的存儲空間;
  • 爲啥說裸機呢?因爲帶系統的軟件系統一般都會帶內存的動態管理函數供使用;
  • 內存碎片是什麼? 首先明確一點,申請內存時會返回一個首地址,從首地址往後的 size 大小的空間都可用,這就說明 malloc必須返回一段連續的內存地址;有些內存動態管理算法是不支持碎片回收的,總是以新地址開始申請。
  • 已驗證,標準 C 庫的mallocfree的函數不支持內存碎片回收;測試方法:循環多次申請->釋放較小的內存塊,然後再申請大的內存塊將失敗。
  • 本文說明的算法是支持內存碎片化回收的,採用把相鄰的空閒內存塊進行合併的方法。

算法原理

數組我們比較熟悉,定義的數組必須實現固定大小,但實際編程中,有太多的情況我們事先無法預測這個數組該定義多大;沒有內存動態管理的裸機系統的做法就是定義一個儘可能大的數組,浪費了RAM,也存在數組溢出的風險。

內存的動態管理:定義一個全局的靜態大數組,先佔個內存的坑,別讓編譯器給釋放或優化掉了;這就是屬於用戶的內存池,進行自我的內存管理;

這個大的內存池怎麼管理比較好呢?本文采用單向鏈表的形式進行管理,如下圖;在這裏插入圖片描述
原理說明:

  • 你可能會說,每個內存塊都要佔用幾個字節用來存儲鏈表指針和內存塊大小,不是浪費嗎?有舍纔能有得,得 > 舍就是值得;

  • 第一次申請內存之前,A_BlockB_Block是沒有的,pxFirstFreeBlock內存塊的可用大小爲大的全局數組所剩空間,此時鏈表只有一個內存塊,按申請的內存大小將pxFirstFreeBlock內存塊分割成兩個;

  • 後面每次申請內存時,會按照已有的內存塊去遍歷鏈表,滿足大小能否滿足,滿足了,剩餘部分是否夠再分割成一個塊的;

  • 你可以想象,這個數組變成了好多個內存塊,2、4、12、23;

  • 如果算法按上述實現,將會產生內存碎片,申請新的內存比已經申請過的內存塊大時,就必須開闢新空間,鏈表中的很多內存將被浪費;

  • 相鄰地址的空閒內存塊進行合併:每次釋放內存塊時,會將其重新放入空閒鏈表中,此時會判斷前後的內存塊和自己地址是否是相鄰的,是就合併內存塊,即內存碎片的回收

代碼實現

敬請期待,最遲三天後更新~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章