内存池实现

/*

* C内存池实现代码

* 作者:WDL

* 出处:http://blog.csdn.net/wuleibilly3

* 转载请注明本博客

*/ 

 

 

 

//内存池

typedef struct _MemTable MemTable;

typedef struct _MemPool MemPool;

typedef struct _MemNode MemNode;

typedef struct _CheckAvail CheckAvail;

 

#define MIN_MEM_BLOCK 12 //最小内存块 最小不得低于12

#define MAX_MEM_BLOCK 128 //最大内存块

 

 

#define SIZE_TO_INDEX(a) ((((DATA_ALIGN(a,4))-MIN_MEM_BLOCK)/4)+1) //获得数据大小所对应的索引

#define INDEX_TO_SIZE(a) (MIN_MEM_BLOCK+4*((a)-1)) //获得索引所对应的数据大小

 

 

#define MAX_INDEX SIZE_TO_INDEX(MAX_MEM_BLOCK)+1 //最大索引 

 

 

#define INIT_BLOCK_SIZE 10 //最初内存块的大小 以后根据递增申请内存

 

#define DATA_ALIGN(a,b) (((a) + ((b) - 1)) & ~((b) - 1)) //数据对齐

 

 

 

//情况检测结构体

typedef struct _CheckAvail{

int flag;

MemNode* data;

}CheckAvail;

 

 

 

 

//0号结点

typedef struct _MemZeroNode{

struct _MemZeroNode *next;

struct _MemZeroNode *up;

int is_avail_flag;

char mem_data[1];

}MemZeroNode;

 

typedef struct _MemBlock{

MemNode* parent; //它是哪个挂接表结点的儿子?

int is_avail_flag; //标志 高位16字节存放 是否可用 低位16字节存放 对应索引

char mem_data[1]; //数据

}MemBlock;

 

typedef struct _MemNode{

 

struct _MemNode *next; //指向下一块

 

char* pfree_avail; //可用空间起始

char* pend; //可用空间结束

 

int num_free_block; //可用块数

 

int num_mem_size; //内存大小

int num_block_total; //块数总计

int num_block_size; //单个块大小

MemBlock* block; //具体可用内存块

 

}MemNode;

 

//内存分配表

typedef struct _MemTable{

int num_maxindex; //最大索引

int *free[MAX_INDEX]; //可用内存表

int num_indexblockcount[MAX_INDEX];   //每个索引对应挂接内存块大小

}MemTable;

 

//内存池

typedef struct _MemPool{

 

MemTable data; //数据 内存池

 

}MemPool;

 

//初始化内存池

void InitMemPool();

//销毁内存池

void DestoryMemPool();

 

 

//获取可用内存

void* MemAlloc(int size);

//释放内存

void MemFree(void* p);

 

 

 

 

MemPool mem_pool;

CheckAvail check_avail;

 

//初始化挂接块数据

void InitHangUpBlock(MemNode* memnode,int blockcount,int index){

 

memnode->next = NULL;

memnode->num_block_size = INDEX_TO_SIZE(index); //单个块

memnode->num_block_total = blockcount*INIT_BLOCK_SIZE; //可用内存块总计

memnode->num_mem_size = memnode->num_block_total * memnode->num_block_size; //申请内存块内存大小

memnode->block = (MemBlock*)malloc( memnode->num_mem_size+1 ); //申请内存块

 

memnode->num_free_block = memnode->num_block_total;

 

memset(memnode->block,0,memnode->num_mem_size+1 ); //初始化挂接块

 

memnode->pfree_avail = (char*)memnode->block; //起始地址

memnode->pend = ((char*)memnode->block+memnode->num_mem_size); //结束地址

 

 

}

 

//初始化

void InitMemPool(){

int i = 0;

//0号表 用来挂接大于MAX_MEM_BLOCK的内存块

mem_pool.data.free[0] = (int*)malloc(sizeof(MemZeroNode));

memset(mem_pool.data.free[0],0,sizeof(MemZeroNode));

 

//首先初始化内存表

for(i = 1 ;i < MAX_INDEX ;i++){

mem_pool.data.free[i] = (int*)malloc(sizeof(MemNode));

mem_pool.data.num_indexblockcount[i] = 1;

memset(mem_pool.data.free[i],0,sizeof(MemNode));

//初始化挂接块数据

InitHangUpBlock((MemNode*)mem_pool.data.free[i],mem_pool.data.num_indexblockcount[i],i);

}

 

mem_pool.data.num_maxindex = MAX_INDEX;

}

 

 

//检测可用内存块

void CheckAvailBlock(MemNode* mem_node){

MemNode* temp;

int flag = 0;

 

for(temp = mem_node;temp != NULL; temp=temp->next){ //没有内存块可用

 

if((temp->pend-temp->pfree_avail)>0) break;

 

if(temp->num_free_block > 0){

check_avail.flag = 2;

check_avail.data = temp;

flag = 1;

}

}

if(temp != NULL){

check_avail.flag = 1;

check_avail.data = temp;

}else{

//二次检测

if(flag == 1){

return;

}else{

check_avail.flag = 3;

//没有内存块了 需要申请

}

}

 

}

 

//清空初始化内存检测

void InitCheckAvailBlock(){

 

check_avail.flag = 0;

check_avail.data = NULL;

 

}

 

//申请新的内存块

MemNode* NewMemBlock(int index){

MemNode *temp,*mem;

 

mem_pool.data.num_indexblockcount[index]++;

 

mem = (MemNode*)mem_pool.data.free[index];

 

for(;mem->next!=NULL;mem=mem->next); //循环到挂接表尾

 

temp = (MemNode*)malloc(sizeof(MemNode)); //申请新的结点

 

mem->next = temp; //挂接新的结点

 

//初始化挂接块数据

InitHangUpBlock(temp,mem_pool.data.num_indexblockcount[index],index);

 

return temp;

 

}

 

//0号表挂接

void* ZeroHangUp(int size){

MemZeroNode *mem,*temp;

int realsize = 0;

realsize = size + sizeof(MemZeroNode)-4;

 

mem = (MemZeroNode*)mem_pool.data.free[0];

 

temp = (MemZeroNode*)malloc(realsize); //申请新内存

temp->is_avail_flag = 0;

temp->next = mem->next; // 挂接

temp->up = mem;

if(mem->next!=NULL) mem->next->up = temp;

mem->next = temp;

 

 

return (void*)temp->mem_data;

}

 

//分配内存

void* MemAlloc(int size){

int realsize = 0;

int index = 0;

int flag = 0;

MemNode* mem_node;

 

if(size == 0) return NULL;

 

realsize = size + sizeof(MemBlock)-4; //0-3字节存储父结点 4-7字节要用来存可用标志位

//8-11字节存储自己

if(realsize > MAX_MEM_BLOCK){

return ZeroHangUp(size);  //超过最大块 MAX_MEM_BLOCK 转到0号表进行挂接

}

 

 

index = SIZE_TO_INDEX(realsize);

 

mem_node = (MemNode*)mem_pool.data.free[index]; //根据索引获得挂接表的位置

 

InitCheckAvailBlock();

CheckAvailBlock(mem_node);

 

flag = check_avail.flag;

 

if(flag == 1){

//情况1 直接可用 O(1)

MemBlock* mem = NULL;

mem_node = check_avail.data;

mem = (MemBlock*)(mem_node->pend-INDEX_TO_SIZE(index)) ;

mem->is_avail_flag |= 0xffff0000; //标记该内存块已经被使用

mem->is_avail_flag |= index; //标记所属索引

mem->parent = mem_node;

mem_node->pend -=  INDEX_TO_SIZE(index);

mem_node->num_free_block--; //可用块数 -1

return (void*)mem->mem_data;

}else if(flag == 2){

//情况2 不直接可用 但是有残余的释放空间可用 O(n)

MemBlock* mem = NULL;

char *mem_start,*mem_end;

mem_node = check_avail.data;

mem_start = mem_node->pfree_avail;

mem_end = mem_node->pfree_avail+mem_node->num_mem_size;

for(;mem_start != mem_end;mem_start += INDEX_TO_SIZE(index)){ //遍历结点所有的挂接块

mem = (MemBlock*)mem_start;

if((mem->is_avail_flag&0xffff0000) == 0){ //检测是否可用

//这块内存可以被用来使用

mem->is_avail_flag |= 0xffff0000; //标记该内存块已经被使用

//mem->is_avail_flag |= index; //标记所属索引

//mem->parent = mem_node;

mem_node->num_free_block--; //可用块数 -1

return (void*)mem->mem_data;

}

}

}else if(flag == 3){

//情况3 新申请的内存块 

MemBlock* mem = NULL;

mem_node = NewMemBlock(index);

mem = (MemBlock*)(mem_node->pend-INDEX_TO_SIZE(index)) ;

mem->is_avail_flag |= 0xffff0000; //标记该内存块已经被使用

mem->is_avail_flag |= index; //标记所属索引

mem->parent = mem_node;

mem_node->pend -=  INDEX_TO_SIZE(index);

mem_node->num_free_block--; //可用块数 -1

return (void*)mem->mem_data;

}

return NULL; //常理说 不可能走到这里

}

 

 

 

 

//释放内存

void MemFree(void* p){

int flag = *(int*)((char*)p-sizeof(int)); 

 

if((flag & 0x0000ffff) != 0){

MemBlock* mem = NULL;

*(int*)((char*)p-sizeof(int)) &= 0x0000ffff; //直接标志可被使用 不释放

//可用内存块 + 1

mem = (MemBlock*)((char*)p-sizeof(int)-sizeof(MemNode*));

mem->parent->num_free_block++;

}else{ //大于MAX_MEM_BLOCK的内存

MemZeroNode *mem = (MemZeroNode*)((char*)p-sizeof(MemZeroNode*)*2-sizeof(int));

mem->up->next = mem->next;

if(mem->next != NULL) mem->next->up = mem->up;

free(mem);

mem = NULL;

}

 

}

 

void DestoryMemPool(){

int i ;

 

MemZeroNode *mem = (MemZeroNode*)mem_pool.data.free[0];

//销毁0号挂接表

for(;mem != NULL;){

MemZeroNode *temp;

temp = mem;

mem = mem->next;

free(temp);

temp = NULL;

}

 

//销毁其它

for(i = 1;i < MAX_INDEX;i++){

MemNode *mem_node = (MemNode*)mem_pool.data.free[i];

for(;mem_node != NULL;){

MemNode *temp;

temp = mem_node;

free(temp->block); //释放具体内存块

temp->block = NULL;

mem_node = mem_node->next;

free(temp); //释放挂接表结点

temp = NULL;

}

}

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值