Cメモリプールの実現
32877 ワード
全体的な設計構想:
まず、メモリブロックの大きさに応じてN*ブロックの大きさの連続メモリ領域を申請する.
メモリブロックを構築する双方向チェーンテーブルは、2種類あり、1つは空きチェーンテーブルである.もう1つはすでに使用されているチェーンテーブルです.この双方向チェーンテーブルも固定サイズのメモリ領域であり、各チェーンノードは現在のメモリブロックのアドレス、ノードの前のノード、および次のノードを格納する.
メモリプールには、チェーンテーブルの開始アドレス、メモリブロックの開始アドレス、空きチェーンテーブルのノード数、空きチェーンテーブルの開始ノード、および終了ノード、チェーンテーブルを使用しているノードの開始ノード、および終了ノードが格納されます.
mem_pool.h
mem_pool.c
まず、メモリブロックの大きさに応じてN*ブロックの大きさの連続メモリ領域を申請する.
メモリブロックを構築する双方向チェーンテーブルは、2種類あり、1つは空きチェーンテーブルである.もう1つはすでに使用されているチェーンテーブルです.この双方向チェーンテーブルも固定サイズのメモリ領域であり、各チェーンノードは現在のメモリブロックのアドレス、ノードの前のノード、および次のノードを格納する.
#define ut_base(TYPE) \
struct { \
TYPE *next; \
TYPE *prev; \
}__attribute__((packed))
/**********************
* define memory block struct _block
* *******************/
typedef struct _block{
char *data;
ut_base(struct _block) base;
}__attribute__((packed)) block;
メモリプールには、チェーンテーブルの開始アドレス、メモリブロックの開始アドレス、空きチェーンテーブルのノード数、空きチェーンテーブルの開始ノード、および終了ノード、チェーンテーブルを使用しているノードの開始ノード、および終了ノードが格納されます.
typedef struct _mem_pool
{
unsigned int blockCount;
unsigned int blockSize;
unsigned int freeSize;
unsigned int freeCount;
struct _block *freeH;
struct _block *freeT;
struct _block *usedH;
struct _block *usedT;
struct _block *pBlockHead;
char *pDataHead;
}__attribute__((packed)) mem_pool;
mem_pool.h
#define increment 64
/********************
* define base list
* *****************/
#define ut_base(TYPE) \
struct { \
TYPE *next; \
TYPE *prev; \
}__attribute__((packed))
/**********************
* define memory block struct _block
* *******************/
typedef struct _block{
char *data;
ut_base(struct _block) base;
}__attribute__((packed)) block;
/********************
* define memory pool
* *****************/
typedef struct _mem_pool
{
unsigned int blockCount;
unsigned int blockSize;
unsigned int freeSize;
unsigned int freeCount;
struct _block *freeH;
struct _block *freeT;
struct _block *usedH;
struct _block *usedT;
struct _block *pBlockHead;
char *pDataHead;
}__attribute__((packed)) mem_pool;
/***********************
* init a memory pool
* *******************/
int pool_init(int blockSize,int blockCount);
/*********************
* add block to mem_pool
* ******************/
int pool_block(size_t unitSize,int blockCount);
/**********************
* alloc memory from memory pool
* ********************/
char *pool_alloc(size_t allocSize);
/************************
* recyc memory from memory pool
* ********************/
int pool_recyc();
/**************************
* free all memory to operation system
* ***********************/
void pool_free();
/***************************
* prt all list of memory pool
* ************************/
void pool_prt();
mem_pool.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mem_pool.h"
static mem_pool pool;
int pool_init(int blockSize,int blockCount)
{
mem_pool *mp=&pool;
int flag=0;
mp->blockCount=mp->freeCount=blockCount;
mp->blockSize=blockSize;
mp->freeH=mp->freeT=NULL;
mp->usedH=mp->usedT=NULL;
flag=pool_block(blockSize,blockCount);
if(flag>0){fprintf(stderr," pool_init error
");return 1;}
return 0;
}
int pool_block(size_t unitSize,int blockCount)
{
mem_pool *mp=&pool;
int i=0;
mp->pBlockHead=(block *)malloc(sizeof(block)*blockCount);
mp->pDataHead=(char *)malloc(sizeof(char)*unitSize*blockCount);
memset(mp->pDataHead,'\0',sizeof(char)*unitSize*blockCount);
mp->blockCount=blockCount;
mp->freeSize=sizeof(char)*unitSize*blockCount;
block *bk=NULL;
for(;i<blockCount;i++)
{
bk=(block *)mp->pBlockHead+(sizeof(block)*i);
char *data=mp->pDataHead+(sizeof(char)*unitSize*i);
bk->base.next=NULL;
bk->base.prev=mp->freeT;
if(mp->freeH==NULL)
{
mp->freeH=mp->freeT=bk;
}
else
{
mp->freeT->base.next=bk;
mp->freeT=bk;
}
bk->data=data;
}
printf(" ---------------pool_block(size_t unitSize=%d,int blockCount=%d)--------------
",unitSize,blockCount);
printf(" mp->freeH : %p,mp->freeH->base.prev : %p
",mp->freeH,mp->freeH->base.prev);
printf(" mp->freeT : %p,mp->freeT->base.next : %p
",mp->freeT,mp->freeT->base.next);
return 0;
}
char *pool_alloc(size_t allocSize)
{
mem_pool *mp=&pool;
int allocCount=0;
int i=0;
if(mp->freeT==NULL)
{
pool_init(mp->blockSize,mp->blockCount);
printf("\t execute pool_init()
");
}
if((allocSize%(mp->blockSize))==0)
{
allocCount=allocSize/(mp->blockSize);
}
else
{
allocCount=allocSize/(mp->blockSize)+1;
}
block *bk=mp->freeT;
for(;i<allocCount;i++)
{
block *prev=mp->freeT->base.prev;
bk->base.prev=NULL;
bk->base.next=NULL;
memset(bk->data,'\0',mp->blockSize);
// printf(" %d,mp->freeT : %p,mp->freeT->base.prev :%p
",i,mp->freeT,mp->freeT->base.prev);
if(mp->usedH==NULL)
{
mp->usedH=mp->usedT=bk;
mp->usedH->base.prev=NULL;
}
else
{
bk->base.prev=mp->usedT;
mp->usedT->base.next=bk;
mp->usedT=bk;
//printf("bk :%p,bk->base.prev :%p,bk->base.next :%p
",bk,bk->base.prev,bk->base.next);
}
//memset(mp->usedT->data,'\0',mp->blockSize);
mp->freeT=prev;
//printf("mp->freeT : %p
",mp->freeT);
bk=mp->freeT;
//printf(" %d,mp->freeT : %p
",i,mp->freeT);
}
mp->freeT->base.next=NULL;
//mp->freeT=mp->pBlockHead+(sizeof(block)*(mp->blockCount-allocCount));
mp->freeCount=mp->freeCount-allocCount;
mp->freeSize=(mp->blockSize)*(mp->blockCount-allocCount);
//memset(mp->pDataHead+mp->freeSize,'\0',allocCount);
printf(" --------pool_alloc(size_t allocSize=%d)--------
",allocSize);
printf(" mp->freeH = %p,mp->freeT = %p
",mp->freeH,mp->freeT);
printf(" mp->usedH = %p,mp->usedT = %p
",mp->usedH,mp->usedT);
return mp->pDataHead+(mp->freeSize);
}
void pool_prt()
{
mem_pool *p=&pool;
block *fr=p->freeH;
block *us=p->usedH;
int i=0;
printf(" \t***********free list->
");
while(fr!=NULL)
{
printf("\t(current = %p,data=%p)",fr,fr->data);
printf(",prev = %p",fr->base.prev);
printf(",next = %p
",fr->base.next);
// printf("\t ## :current->data =%p",fr->data);
// printf(",prev->data = %p",fr->base.prev->data);
// printf(",next->data = %p
",fr->base.next->data);
fr=fr->base.next;
i++;
}
printf(" \tfreelist length = %d
",i);
i=0;
printf(" \t p->freeH = %p,p->freeT = %p
",p->freeH,p->freeT);
printf(" \t**********used list->
");
while(us!=NULL)
{
printf("\t(current = %p,data=%p",us,us->data);
printf(",prev = %p",us->base.prev);
printf(",next = %p
",us->base.next);
// printf("\t ## :current->data =%p",us->data);
//printf(",prev->data = %p",us->base.prev->data);
//printf(",next->data = %p
",us->base.next->data);
us=us->base.next;
i++;
}
printf(" \tusedlist length = %d
",i);
printf(" \tp->usedH = %p,p->usedT = %p
",p->usedH,p->usedT);
printf("
");
}
void pool_free()
{
mem_pool *p=&pool;
free(p->pBlockHead);
free(p->pDataHead);
p->pBlockHead=NULL;
p->pDataHead=NULL;
printf("\t mem_pool free
");
}
int pool_recyc(size_t freeSize)
{
mem_pool *mp=&pool;
int cyc=0,i=0;
if(freeSize>(mp->blockSize*mp->blockCount))
{
fprintf(stderr," freeSize is over all memory size in memory pool
");
return 1;
}
if((freeSize%mp->blockSize)==0)
{
cyc=freeSize/(mp->blockSize);
}
else
{
cyc=(freeSize/mp->blockSize)+1;
}
printf(" --------pool_recyc(size_t freeize=%d)--------
",freeSize);
printf(" recyc block count = %d
",cyc);
printf(" begin: mp->freeH = %p,mp->freeT = %p
",mp->freeH,mp->freeT);
printf(" begin: mp->usedH = %p,mp->usedT = %p
",mp->usedH,mp->usedT);
printf(" begin: mp->freeCount = %d,mp->freeSize = %d
",mp->freeCount,mp->freeSize);
if(mp->usedH==NULL)
{
fprintf(stderr," all block is not used in memory pool
");
return 1;
}
block *cur=mp->usedT;
for(;i<cyc;i++)
{
//link a block to free list
block *prev=cur->base.prev;
mp->freeT->base.next=cur;
cur->base.prev=mp->freeT;
memset(cur->data,'\0',mp->blockSize);
mp->freeT=cur;
//mp->usedT=mp->usedT->base.prev;
cur=prev;
mp->usedT=prev;
//remove a block from used
}
if(cyc==(mp->blockCount-mp->freeCount))
{
mp->usedH=mp->usedT=NULL;
}
if(mp->usedT!=NULL)
{
if(mp->usedT==mp->usedH)
{
mp->usedH->base.prev=NULL;
mp->usedT->base.next=NULL;
}
}
mp->freeT->base.next=NULL;
mp->freeCount=mp->freeCount+cyc;
mp->freeSize=mp->freeSize+(mp->blockSize*cyc);
printf(" end: mp->freeH = %p,mp->freeT = %p
",mp->freeH,mp->freeT);
printf(" end: mp->usedH = %p,mp->usedT = %p
",mp->usedH,mp->usedT);
printf(" end: mp->freeCount = %d,mp->freeSize = %d
",mp->freeCount,mp->freeSize);
return 0;
}
int main(void)
{
printf(" pool_init(%d,%d) = %d
",4,100,pool_init(5,10));
pool_prt();
char *p=pool_alloc(14);
memset(p,'1',13);
printf(" char *p =%s
",p);
pool_prt();
pool_recyc(12);
pool_prt();
char *p1=pool_alloc(6);
memset(p1,'8',5);
printf("char *p1 = %s
",p1);
pool_prt();
pool_recyc(3);
printf(" char *p =%s
",p);
pool_prt();
pool_free();
return 0;
}