C 内存池的实现
总体的设计思路:
首先按照内存块的大小申请N*块大小的连续内存区域。
构造内存块的双向链表,有2种,一种是空闲链表;另外一种为已经使用的链表。该双向链表也是一块固定大小的内存区域,每个链表节点存储了当前内存块的地址、该节点上一个节点以及下一个节点。
#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\n");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)--------------\n",unitSize,blockCount); printf(" mp->freeH : %p,mp->freeH->base.prev : %p\n",mp->freeH,mp->freeH->base.prev); printf(" mp->freeT : %p,mp->freeT->base.next : %p\n",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() \n"); } 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\n",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\n",bk,bk->base.prev,bk->base.next); } //memset(mp->usedT->data,'\0',mp->blockSize); mp->freeT=prev; //printf("mp->freeT : %p\n",mp->freeT); bk=mp->freeT; //printf(" %d,mp->freeT : %p\n",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)--------\n",allocSize); printf(" mp->freeH = %p,mp->freeT = %p\n",mp->freeH,mp->freeT); printf(" mp->usedH = %p,mp->usedT = %p\n",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->\n"); while(fr!=NULL) { printf("\t(current = %p,data=%p)",fr,fr->data); printf(",prev = %p",fr->base.prev); printf(",next = %p\n",fr->base.next); // printf("\t ## :current->data =%p",fr->data); // printf(",prev->data = %p",fr->base.prev->data); // printf(",next->data = %p\n",fr->base.next->data); fr=fr->base.next; i++; } printf(" \tfreelist length = %d\n",i); i=0; printf(" \t p->freeH = %p,p->freeT = %p\n",p->freeH,p->freeT); printf(" \t**********used list->\n"); while(us!=NULL) { printf("\t(current = %p,data=%p",us,us->data); printf(",prev = %p",us->base.prev); printf(",next = %p\n",us->base.next); // printf("\t ## :current->data =%p",us->data); //printf(",prev->data = %p",us->base.prev->data); //printf(",next->data = %p\n",us->base.next->data); us=us->base.next; i++; } printf(" \tusedlist length = %d\n",i); printf(" \tp->usedH = %p,p->usedT = %p\n",p->usedH,p->usedT); printf("\n"); } void pool_free() { mem_pool *p=&pool; free(p->pBlockHead); free(p->pDataHead); p->pBlockHead=NULL; p->pDataHead=NULL; printf("\t mem_pool free \n"); } 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\n"); return 1; } if((freeSize%mp->blockSize)==0) { cyc=freeSize/(mp->blockSize); } else { cyc=(freeSize/mp->blockSize)+1; } printf(" --------pool_recyc(size_t freeize=%d)--------\n",freeSize); printf(" recyc block count = %d\n",cyc); printf(" begin: mp->freeH = %p,mp->freeT = %p\n",mp->freeH,mp->freeT); printf(" begin: mp->usedH = %p,mp->usedT = %p\n",mp->usedH,mp->usedT); printf(" begin: mp->freeCount = %d,mp->freeSize = %d\n",mp->freeCount,mp->freeSize); if(mp->usedH==NULL) { fprintf(stderr," all block is not used in memory pool\n"); 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\n",mp->freeH,mp->freeT); printf(" end: mp->usedH = %p,mp->usedT = %p\n",mp->usedH,mp->usedT); printf(" end: mp->freeCount = %d,mp->freeSize = %d\n",mp->freeCount,mp->freeSize); return 0; } int main(void) { printf(" pool_init(%d,%d) = %d\n",4,100,pool_init(5,10)); pool_prt(); char *p=pool_alloc(14); memset(p,'1',13); printf(" char *p =%s\n",p); pool_prt(); pool_recyc(12); pool_prt(); char *p1=pool_alloc(6); memset(p1,'8',5); printf("char *p1 = %s\n",p1); pool_prt(); pool_recyc(3); printf(" char *p =%s\n",p); pool_prt(); pool_free(); return 0; }