以下爲看視頻筆記..........
1. 內存池的介紹
動態內存堆可以分配任意大小的內存塊,非常靈活和方便。但其存在明顯的缺點:一是分配效率不高,在每次分配時,都要進行空閒內存塊查找;二是容易產生內存碎片。
爲了提高內存分配的效率,並且避免內存碎片,RT-Thread 提供了另外一種內存管理方法:內存池(Memory Pool )
內存池是一種內存分配方式,用於分配大量大小相同的小內存塊。使用內存池可以極大地加快內存分配與釋放的速度,且能儘量避免內存碎片化。
RT-Thread的內存池支持線程掛起功能,當內存池中無空閒內存塊時,申請線程會被掛起,直到內存池中有新的可用內存塊,再將掛起的線程喚醒。基於這個特點內存池非常適合需要通過內存資源進行同步的場景。
2. 內存池工作機制
內存池在創建時先從系統中獲取一大塊內存 ( 靜態或動態),然後分成相同大小的多個小內存塊,這些小內存塊通過鏈表連接起來(此鏈表也稱爲空閒鏈表)。線程每次申請分配內存塊的時候,系統從空閒鏈表中取出鏈頭上第一個內存塊, 提供給申請者。
3. 內存池控制塊
在RT_Thread中,內存池控制塊是操作系統用於管理內存池的一個數據結構。
struct rt_mempool
{
struct rt_object parent:
void *start_address;//保存申請的內存的地址
rt_size_t size; //記錄大內存塊的大小
rt_size_t block_size; //記錄大內存塊中小內存塊的大小
rt_uint8_t *block_list; //小內存塊的列表
rt_size_t block_total_count;//總共有多少小內存塊
rt_size_t block_free_count; //當前小內存塊空閒的個數
rt_list_t suspend_thread; //內存塊支持掛起,記錄線程掛起在內存池上的列表
rt_size_t suspend_thread_count;//記錄線程掛起在內存池上的數目
}
typedef struct rt_mempool *rt_mp_t //內存塊的指針型定義
定義靜態內存池:struct rt_mempool static_mp
定義動態內存池:rt_mp_t dynamic_mp
4. 內存池的操作
靜態內存池的初始化與脫離
rt_err_t rt_mp_init(struct rt_mempool *mp,const char *name,
void *start,rt_size_t size,rt_size_t block_size)
//第一個參數爲內存控制塊的地址,第二個參數爲內存控制塊起一個名字,注意RT-Thread的所有對象都要起一個名稱。第三個參數爲系統的內存地址輸入給參數,可以先用數組的方式定義出來。第四個參數爲內存池的大小。第五個參數爲內存池中內存塊的大小(數值爲4的整數倍)。計算內存池中有多少內存塊:
//size/(block_size+4).內存塊都是用鏈表連接的,4是一個指針的長度
rt_err_t rt_mp_detach(struct rt_mempool *mp)
//第二個參數爲內存塊數目。第三個參數爲內存塊的大小
動態內存池的創建與刪除
rt_mp_t rt_mp_create(const char *name,rt_size_t block_count,rt_size_t block_size)
rt_err_t rt_mp_delete(rt_mp_t mp)
申請內存塊
void rt_mp_alloc(rt_mp_t mp ,rt_int32_t time)
//第一個參數爲內存塊控制塊的地址,指示從哪個內存池分配內存控制塊,第二個參數爲當內存池滿時線程掛起時間,當time>0,掛起time 時間,當time = 0,立即返回,time < 0 ,線程阻塞在內存池的申請上。
釋放內存塊
void rt_mp_free(void *block)//輸入內存塊的地址,釋放那個內存塊
5. 例程在memp_sample.c