memcache中管理內存的數據結構如下:
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;

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