Cメモリプールの実現

32877 ワード

全体的な設計構想:
まず、メモリブロックの大きさに応じて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; }