在innodb中實現了自己的內存池系統和內存堆分配系統,在innodb的內存管理系統中,大致分為三個部分:基礎的內存塊分配管理、內存伙伴分配器和內存堆分配器。innodb定義和實現內存池的主要目的是提供內存的使用率和效率,防止內存碎片和內存分配跟蹤和調試。我們先來看看他們的關系和結構。
以下是它的關系結構圖:
上圖中的:
ut_mem_block塊是基礎內存管理
Buddy allocatZ喎?http://www.Bkjia.com/kf/ware/vc/" target="_blank" class="keylink">vcsrHxNq05rvvsOm31sXkxvc8L3A+CjxwPiAgICBtZW1faGVhcMrHxNq05rbRt9bF5Mb3PC9wPgo8aDE+MS67+bShxNq05rncwO08L2gxPgppbm5vZGLW0LXExNq05rfWxeS6zcTatObKzbfFysfNqLn9zbPSu7XEveG5ub340NC53MDto6y+38zltcTKtc/W1Np1dDBtZW0uaLrNdXQwbWVtLmO1sdbQo6zG5NbQ1+7W2NKqtcS+zcrHttRtYWxsb2O6zWZyZWW1xLfi17Cho82ouf3Su7j2wbSx7b3hubnM5cC0udzA7dLRvq231sXktcTE2rTmo6y94bm5zOXI58/Co7oKPHByZSBjbGFzcz0="brush:sql;"> typedef ut_mem_block_struct
{
ulint size; /*這個被分配block的內存大小*/
ulint magic_n; /*節點魔法字,用於校驗所用*/
UT_LIST_NODE_T(ut_mem_block_t) mem_block_list; /*block list node,指定prev node和next node*/
};關於block的list定義是個全局的變量,UT_LIST_BASE_NODE_T(ut_mem_block_t)
ut_mem_block_list;所有分配的block都會加入到這個list當中。在ut_malloc_low函數分配內存的時候會將分配的block加入到list當中,在ut_free的時候會所釋放的內存所在的block從list當中刪除。除了這兩個函數以外,innodb還提供ut_free_all_mem函數來釋放所有分配的block和統計分配內存的總數ut_total_allocated_memory功能。
基礎內存管理的方法如下:
ut_malloc_low 分配一個n長度的內存塊,並將分配的塊記錄到ut_mem_block_list當中.
ut_malloc 與ut_malloc_low功能相同,但是會用0初始化所分配的內存。
ut_free 釋放一個分配的內存塊,並將其從ut_mem_block_list當中刪除。
ut_free_all_mem 釋放ut_mem_block_list所有的內存塊並清空ut_mem_block_list
以上函數是支持多線程並發操作的,也就是說是線程安全的。
innodb這樣做的目的是保證所有malloc出去的內存都在 ut_mem_block_list當中,以便管理。
基礎內存管理的結構如下:
struct mem_pool_struct { byte* buf; /*整體內存的句柄*/ ulint size; /*整體內存大小*/ ulint reserved; /*當前分配出去的總內存大小*/ mutex mutex; /*多線程互斥量*/ UT_LIST_BASE_NODE_T(mem_area_t) free_list[64]; /*area_t鏈表數組,每個數組單元能管理2的i次方內存塊列表,i是數組的下標*/ };
struct mem_area_struct { ulint size_and_free; /*area的內存大小(一定是2的次方),最後一個bit表示是否已經釋放*/ UT_LIST_NODE_T(mem_area_t) free_list; /*area鏈表的上下area,因為buddy area是會分裂的,有可能多個*/ };mem_area_t是一個buddy的內存區域,也就是mem_area_struct。以下是一個32位機器管理1024字節內存塊的buddy list分布:
struct mem_block_info_struct { ulint magic_n; /*魔法字*/ char file_name[8]; /*分配內存的文件*/ ulint line; /*分配內存的文件所在行*/ ulint len; /*block的長度*/ ulint type; /*依賴的底層分配類型,有DYNAMIC、BUFFER、BTR_SEARCH三種類型*/ ibool init_block; /*是否是外部分配的內存塊*/ ulint free; /*被占用的空間大小*/ ulint start; /*可分配內存的起始位置*/ byte* free_block; /*備用block,僅僅在BTR_SEARCH方式可用*/ UT_LIST_BASE_NODE_T(mem_block_t) base; UT_LIST_NODE_T(mem_block_t) list; };備注:mem_block_info_struct/mem_block_info_t/mem_block_t/mem_heap_t是等價