概述
AliOS Things操作系統內核通過內存管理實現應用程序可以調用標準C庫的malloc和free接口來動態的分配和釋放內存。
內存管理函數
函數名 | 描述 |
aos_malloc() | 從系統heap分配內存給用戶 |
aos_zalloc() | 從系統heap分配內存給用戶,并且將分配的內存初始化為0 |
aos_calloc() | 從系統heap分配內存給用戶,并且將分配的內存初始化為0 |
aos_realloc() | 重新調整之前調用 |
aos_free() | 內存釋放函數 |
內存分配算法
AliOS Things內存管理采用類buddy伙伴算法,以及blk快速小內存申請算法相結合的策略。
buddy算法:
Buddy算法申請的內存最小為8字節對齊,可申請的最大長度除了受堆空間總大小限制外還可通過編譯宏配置。系統提供的Buddy算法是通過32 bit的位圖結構來掛載對應的空閑鏈表,bit n代表內存塊對應的type,其下面掛載了長度范圍 (2^(n- 1 + off) ~ 2^(n + off) - 1)的空閑塊,其中off值主要是考慮利用了原本較小長度塊的低bit。
內存申請時,優先從對應type的空閑鏈表中申請;如果沒有空閑,則從 type+1 的位置申請內存,并將多余的空閑內存塊做拆分并重新放入對應的空閑鏈表位置;每個內存塊維測信息,包括如魔術字、多級申請調用棧、是否空閑等信息,便于內存踩踏、泄漏、重復釋放等問題的定位。
內存釋放時,考慮前后的內存塊是否也空閑,如果是,則進行內存塊合并,并插入相應type的空閑鏈表位置。 優點:能夠滿足絕大多數場景的內存申請需求; 可以申請最大范圍內任意長度的內存; 內存碎片整理已經相當出色; 有充分的維測信息,便于問題定位。 缺點:內存維測信息較多,有一定的空間浪費; 內存不停地拆分組合,一定程度上影響效率; 長期運行過多的小內存會出現碎片,會隔斷大內存空間。
blk小內存快速申請:
blk小內存算法申請的內存最小為4字節對齊,小于RHINO_CONFIG_MM_BLK_SIZE大小的內存塊會優先從blk算法中申請,不夠的再從通過buddy申請。
內存申請時,優先從對應type的空閑鏈表中申請;如果沒有空閑,則先考慮從空閑資源池拉取一段空閑資源補充;如果空閑資源不足,則從 type+1 的位置申請內存(以此類推)申請過程不涉及拆分。
內存釋放時,直接掛在到對應type的空閑鏈表內,釋放不涉及合并。
優點:申請效率高; 避免過多小內存碎片。 缺點:內存維測信息少,出現問題較難定位; 申請的內存大小有限制,一般為1K以下。
常用配置
內存的常用配置都在各個單板的k_config.h中,如果不需修改,則會使用k_default_config.h里面的默認配置。當然由于其本身是宏定義,也可在board對應的YAML中定義。
打開關閉內存模塊功能
def_config:
RHINO_CONFIG_MM_TLF: 1
打開關閉buddy內存模塊的維測功能
def_config:
RHINO_CONFIG_MM_DEBUG: 1
內存維測打開時,記錄內存申請時的多少級調用棧
def_config:
RHINO_CONFIG_MM_TRACE_LVL: 8
Buddy算法最大支持申請的內存大小bit位 實際大小換算為 1ul << RHINO_CONFIG_MM_MAXMSIZEBIT
def_config:
RHINO_CONFIG_MM_MAXMSIZEBIT: 28
打開關閉固定長度小內存塊快速申請
def_config:
RHINO_CONFIG_MM_BLK: 1
固定長度小內存塊總空間大小(byte)
def_config:
RHINO_CONFIG_MM_TLF_BLK_SIZE: 8192
設定從blk小內存申請的閾值(byte)即
def_config:
RHINO_CONFIG_MM_BLK_SIZE: 256
注:blk目前最大支持1K以下的小內存塊如果需要調整可修改內部配置 MM_BLK_SLICE_BIT一般無需修改
API說明
使用示例
該示例可配置到helloworld_demo中運行,相關代碼的下載、編譯和固件燒錄均依賴AliOS Things配套的開發工具 ,所以首先需要參考《AliOS Things集成開發環境使用說明之搭建開發環境》,下載安裝 。 待開發環境搭建完成后,可以按照以下步驟進行示例的測試。
步驟1 創建或打開工程
打開已有工程
如果用于測試的案例工程已存在,可參考《AliOS Things集成開發環境使用說明之打開工程》打開已有工程。
創建新的工程
組件的示例代碼可以通過編譯鏈接到AliOS Things的任意案例(solution)來運行,這里選擇helloworld_demo案例。helloworld_demo案例相關的源代碼下載可參考《AliOS Things集成開發環境使用說明之創建工程》。
步驟2 添加組件
helloworld_demo組件的package.yaml中添加
depends:
- osal_aos: dev_aos # helloworld_demo中引入osal_aos組件
步驟3 下載組件
在已安裝了的開發環境工具欄中,選擇Terminal -> New Terminal啟動終端,并且默認工作路徑為當前工程的workspace,此時在終端命令行中輸入:
aos install osal_aos
上述命令執行成功后,組件源碼則被下載到了./components/osal_aos路徑中。
步驟4 添加示例
osal_aos組件的package.yaml中添加example示例代碼:
depends:
- rhino: dev_aos
- cli: dev_aos # 添加cli依賴
source_file:
- "*.c"
- "example/mem_example.c" # 添加 mem_example.c
步驟5 編譯固件
在示例代碼已經添加至組件的配置文件,并且helloworld_demo已添加了對該組件的依賴后,就可以編譯helloworld_demo案例來生成固件了,具體編譯方法可參考《AliOS Things集成開發環境使用說明之編譯固件》。
步驟6 燒錄固件
helloworld_demo案例的固件生成后,可參考《AliOS Things集成開發環境使用說明之燒錄固件》來燒錄固件。
步驟7 打開串口
固件燒錄完成后,可以通過串口查看示例的運行結果,打開串口的具體方法可參考《AliOS Things集成開發環境使用說明之查看日志》。
當串口終端打開成功后,可在串口中輸入help來查看已添加的測試命令。
步驟8 測試示例
CLI命令行輸入:
mem_example
關鍵日志:
[aos_mem_example]aos_malloc success!
[aos_mem_example]aos_zalloc success!
[aos_mem_example]aos_calloc success!
[aos_mem_example]aos_realloc success!
注意事項
實際內存申請釋放應統一通過malloc/free接口,其內部已經對接了aos_malloc/aos_free接口。
內存申請使用的堆統一由g_mm_region數據結構初始化(傳入堆起點和長度),并在aos_init內核初始化接口中默認完成了內存模塊的初始化。
FAQ
Q1: 內存模塊的維測功能如何打開?
答:通過打開宏RHINO_CONFIG_MM_DEBUG即可打開內存管理模塊的維測信息;其包含內存頭魔術字、內存申請的調用棧以及當前內存空閑情況等等。 其中blk算法不包含維測信息。
Q2:如何查看當前內存的使用情況
答:通過在cli中輸入 dumpsys_mm_info ,將所有內存塊的使用情況,以及整體的占用空閑情況輸出。