C 工具庫6 通用記憶體分配器

2021-09-06 05:12:03 字數 2977 閱讀 3428

struct head_fix

;

這個頭不會返回給上層應用,是給釋放記憶體使用的.因為記憶體的請求是對齊到4位元組的,小於1024位元組的請求,被分成256個分配大小,分別是4,

8,12,....1024.每個大小的請求由乙個fix_obj_pool處理.idx的作用就是記錄是由哪個fix_obj_pool分配的記憶體.還有一點要注意的是,head_fix

本身占用了4個位元組,所以fix_obj_pool分配的物件大小實際是請求大小對齊到4倍數的大小再加上4.例如如果分配1個位元組,對齊到4就是4位元組,

所以實際分配記憶體的大小是8,只有後面4個位元組會返回給上層應用.

這種空間的浪費對於小的記憶體請求有點過分了,所以在實際使用中,這個所謂的通用記憶體分配器,其實不是為編譯時就已經可以確定大小的物件

使用的,對於編譯期就確定大小的物件,應該直接使用fix_obj_pool.只有那些在執行時才確定大小的記憶體分配請求,例如字串,變長結構等

才應該使用通用記憶體分配器.

下面介紹chunk_idx的作用.

首先回顧fix_obj_pool的實現,乙個chunk中的所有物件在位址上都是連續的,當chunk的空間不夠時,會再分配乙個chunk,然後將這些chunk按期首地

址大小的公升序排序.這樣,釋放乙個物件時,可以根據物件位址使用2分查詢快速的找到物件歸屬的chunk.

雖然2分查詢效率是比較高的,但最好還是能避免.在單獨使用fix_obj_pool的情況小,一般可以大致估算到系統中最大可能會分配多少個這類物件.

在建立fix_obj_pool時,傳入這個估算值,就可以生成乙個大小基本符合要求的chunk,這樣幾乎在大多數情況下都避免了釋放記憶體時的一次2分查詢.

但對於通用記憶體分配器,我們不太好估計這個值,所以,chunk的初始大小一般都不會設得太大.為了避免二分查詢,在分配分時,通過呼叫:

void *pool_alloc2(struct fix_obj_pool *pool,unsigned short *chunk_idx)

把chunk的下標一併返回,釋放時直接把這個下標傳進去就可以定位到正確的chunk了.

下面是通用記憶體分配器的**:

mem_allocator.h

#ifndef _mem_allocator_h

#define _mem_allocator_h

struct allocator;

/** max:可以分配的最大請求位元組數

*/struct allocator *allocator_create(unsigned int max);

void allocator_destroy(struct allocator **);

void *allocator_alloc(struct allocator*,int);

void allocator_dealloc(struct allocator*,void*);

#endif

mem_allocator.c

#include "

mem_allocator.h

"#include "

../first_fit/first_fit.h

"#include "

../first_fit/first_fit_define.h

"#include "

../fix_obj_pool/fix_obj_pool.h

"#include "

"#include

#include

#include

#include

#define first_fit_default_size 1024*1024*16 //

預設first_fit分配器大小是16mb

/** fix_obj_pool用於分配從1-1024位元組大小的請求

* 請求對齊到4位元組.所以總共有1024/4 = 256種大小

*/struct allocator

;struct head_fix

;struct head_first_fit

;struct chunk;

extern

void *pool_alloc2(struct fix_obj_pool*,unsigned short *chunk_idx);

extern

void pool_dealloc2(struct fix_obj_pool *pool,unsigned short chunk_idx,void* obj);

struct allocator *allocator_create(unsigned int max)

}al->first_fits = vector_create(sizeof(struct first_fit_pool*),0);

struct first_fit_pool *first_fit = first_fit_create(first_fit_default_size);

if(!first_fit)

vector_push_back(struct first_fit_pool*,al->first_fits,first_fit);

return al;

}void allocator_destroy(struct allocator **al)

i = 0;

for( ; i < 1024/4;++i)

free(*al);

*al = 0;

}void *allocator_alloc(struct allocator *al,int size)

if(!hff)

if(!hff)

void *ret = (void*)((char*)hff + sizeof(*hff));

return ret;}}

else

}void allocator_dealloc(struct allocator *al,void *ptr)

}else

}}

IPV6通用原理培訓

描述ipv6的基本特點 列出主流ipv6的網路演進方案 列出ipv6不同的演進方案使用場景 根據現網情況選擇合理的ipv6演進方案 提出了nat方案 nat私網位址轉換為私網位址 該技術為資料報頭轉化為另乙個資料報頭 nat444 即再使用者訪問公共網路之前做兩次nat轉換 ipv4轉ipv4再轉i...

正規表示式6 通用搜尋

上一章提到了模糊搜尋,字元組就是一種,因為它不指定具體哪乙個字元了,那麼,還敢再模糊一些麼?沒問題,這章來看更模糊一些的 通用搜尋 通用搜尋會用到轉義字元,希望能你已經理解了轉義字元。如果還不理解,請回到 轉義搜尋 那章再理解一下。下面是常用的通用搜尋的格式 表示式含義例子.搜尋任意乙個字元,但是不...

C語言學習 6 記憶體分配

一 傳統陣列的缺點 1 陣列的長度必須事先定製,且只能是常整數,不能是變數 intlen 5 inta len error 2 傳統形式定義的陣列,該程式的記憶體程式設計師無法手動釋放 include void f void 這二十個位元組的儲存空間程式設計師無法手動程式設計釋放它 只能在本函式執行...