這一節學習基礎知識:所用到的資料結構。首先看記憶體池的介面:
code:
#ifndef _mem_pool_h
#define _mem_pool_h
static
size_t __freelist_index(size_t bytes);
static
size_t __round_up(size_t bytes);
static
void *mem_malloc(size_t n);
static
void mem_free(void *p, size_t n);
static
void *mem_realloc(void* ptr, size_t new_sz, size_t old_sz)
static
void *refill(size_t n);
static
char *chunk_alloc(size_t size, int *nobjs);
#endif
用到的常量與變數:
code:
#define __max_bytes 128 /* 小型區塊的上限 */
#define __align 8 /* 小型區塊的上調邊界 */
#define __nfreelists __max_bytes / __align /* 鍊錶個數 */
obj *free_list[__nfreelists]; /* 自由鍊錶 */
static
char *start_free; /* 記憶體池起始位置 */
static
char *end_free; /* 記憶體池結束位置 */
static
size_t heap_size; /* 記憶體池大小 */
這裡值得一提的是共用體obj,定義如下:
code:
typedef
union obj obj;
一般情況下我們構建單鏈表時需要建立如下的乙個結構體:
struct obj ;
使用者申請12位元組的空間時使用時如下方式:
obj *pj = (obj *)malloc(12 + sizeof(struct obj));
pj->next = null;
pj->p = (char*)p + sizeof(struct obj);
pj->size = 12;
但是採用這種方式有個缺點就是我們需要花費額外的開銷(記錄指向下乙個結點的指標和大小),我們可以通過直接定位鍊錶在free_list陣列中的位置來減掉 size 的開銷,因為 free_list[0] 指向的是8 bytes的區塊,free_list[1] 指向的是16 bytes的區塊……。但仍需承擔 next 和 p 指標的開銷。
當我們採用
union obj ;
時,sizeof(obj)的大小為4,當然我們更不需負擔這4個位元組的開銷。因為我們可以充分利用union的特性——同一時刻只存在乙個變數。當我們構建空閒鍊錶時,我們通過free_list_link指向下乙個obj,當把這個obj分配出去的時候,我們直接返回client_data的位址。這樣我們就不會在使用者申請的空間上新增任何東西,達到了一物二用的結果。
接下來看幾個簡單的函式:
code:
static
size_t __freelist_index(size_t bytes)
static
size_t __round_up(size_t bytes)
__freelist_index的作用是函式根據區塊的大小,決定使用第n號free-list。n從0算起。__round_up用於將bytes上調至 __align 的倍數。
接下來要進入幾個主要的函式學習了。
stl記憶體池學習(一) 記憶體池初認識
序號 0123 4567 891011 1213 1415 串接區塊816 2432 4048 5664 7280 8896 104112 120128 範圍1 8 9 16 17 24 25 32 33 40 41 48 49 56 57 64 65 72 73 80 81 88 89 96 97...
stl記憶體池學習(一) 記憶體池初認識
序號 0123 4567 891011 1213 1415 串接區塊816 2432 4048 5664 7280 8896 104112 120128 範圍1 8 9 16 17 24 25 32 33 40 41 48 49 56 57 64 65 72 73 80 81 88 89 96 97...
STL記憶體池講解
簡單說下 設計記憶體池的目的主要是為了解決在一些特殊的場合 比如 網路程式設計時接受資料報 頻繁的建立和銷毀 造成的大量的記憶體碎片和降低效率。在stl的記憶體池中可以看到 它的實現是利用了乙個自由鍊錶陣列 obj free lists 陣列中每個元素都是乙個自由鍊錶的頭指標 它指向乙個由多個記憶體...