memcache中管理內(nèi)存的數(shù)據(jù)結(jié)構(gòu)如下:
typedef struct {
unsigned int size; /* sizes of items */
unsigned int perslab; /* how many items per slab */

void **slots; /* list of item ptrs */
unsigned int sl_total; /* size of previous array */
unsigned int sl_curr; /* first free slot */

void *end_page_ptr; /* pointer to next free item at end of page, or 0 */
unsigned int end_page_free; /* number of items remaining at end of last alloced page */

unsigned int slabs; /* how many slabs were allocated for this class */

void **slab_list; /* array of slab pointers */
unsigned int list_size; /* size of prev array */

unsigned int killing; /* index+1 of dying slab, or zero if none */
} slabclass_t;

程序中有一個(gè)全局的數(shù)組
static slabclass_t slabclass[POWER_LARGEST + 1]用于保存slab,預(yù)分配內(nèi)存池時(shí)調(diào)用的是void slabs_init(const size_t limit, const double factor) 函數(shù),其中l(wèi)imit是內(nèi)存池的最大容量,factor是分配時(shí)的增長因子.
比方說,加入factor是2,第一個(gè)在slabclass數(shù)組中的slab的每個(gè)item大小是128字節(jié),那么下一個(gè)slab每個(gè)item的大小就是128*2,再下一個(gè)就是128*2*2(注意,為了簡化問題的說明,上面沒有考慮地址對齊的因素).
在預(yù)分配內(nèi)存池時(shí),最多給每個(gè)slab保存item的容量是1M內(nèi)存,這個(gè)數(shù)值由#define POWER_BLOCK 1048576決定.
因此,slab中的幾個(gè)元素在預(yù)分配內(nèi)存時(shí)是這么定的:
size有一個(gè)起始值,這個(gè)值以后的增長由factor決定,增長的過程前面已經(jīng)闡述過了;
perslab保存的是一個(gè)slab存放的item數(shù)量,因此perslab = POWER_BLOCK / slabclass[i].size;
如果預(yù)先分配一段內(nèi)存供使用的話,也就是沒有定義DONT_PREALLOC_SLABS宏,那么就調(diào)用slabs_preallocate進(jìn)行預(yù)分配內(nèi)存.
其中,end_page_ptr指向這個(gè)預(yù)分配好的指針,end_page_free表示的是目前空閑可用item的數(shù)量,在預(yù)分配時(shí),這個(gè)值與perslab相同.
在這個(gè)內(nèi)存池模型中,每個(gè)page實(shí)際上是一個(gè)數(shù)組,數(shù)組中每個(gè)元素的大小就是這個(gè)slab中item的大小.
另外,slots保存的是釋放出來的item指針,sl_total表示總的數(shù)量,sl_curr表示的是目前可用的已經(jīng)釋放出來的item數(shù)量.
每一次要分配內(nèi)存的時(shí)候,首先根據(jù)需要分配的內(nèi)存大小在slabclass數(shù)組中查找索引最小的一個(gè)大于所要求內(nèi)存的slab,如果slots不為空,那么就從這里返回內(nèi)存,否則去查找end_page_ptr,如果也沒有,那么就只能返回NULL了.
每一次釋放內(nèi)存的時(shí)候,同樣的找到應(yīng)該返回內(nèi)存的slab元素,改寫前面提到的slot指針和sl_curr數(shù).
有點(diǎn)倉促,以后再完善~~