用C语言实现的简易内存池

来源:互联网 发布:ubuntu 创建文件权限 编辑:程序博客网 时间:2024/05/17 22:50
    这套内存池代码其实是我前不久刚刚进公司时,我的师傅安排给我的一个“作业”,可能目的是试探一下我的Coding能力,看看我的编码风格吧。现在把它写在这里和大家分享,这个代码并不是多么高效的内存池,只是作为一个简单的练习,开拓自己的思维,锻炼自己的链表编程能力。所以如果有人想找高效代码用在项目里,我建议还是使用开源的框架比较好。代码如果有BUG请指教,本人小白,大牛勿喷!
    内存池的使用背景:
    1.使用malloc系统函数分配内存虽然很方便,但是很容易产生碎片。
    2.为了使关键模块在需要内存时,避免获取不到内存的麻烦。关键模块创建时,可以预先占用模块所需要的最大 内存,由模块内自行分配释放。
    3.采用预占内存方式的模块,可以明确确定该模块所需要的内存资源大小。有利于硬件资源的确定。
    我的编程思想是建立一个内存池结构体,存储内存池的信息,包括内存块数量、大小、已使用数量、起始地址、终止地址、指向第一个节点的链表指针。

    注释中的所谓节点也是一个结构体,包含内存块指针,节点链表指针。分配内存块时,检测下池中是否有空闲,有则分配,并从池中删去节点,直到释放内存块时再插入链表。

使用完内存池后,释放内存池。这套代码中避免了遍历操作,而且统一开辟、释放内存,可以有效提高效率。


代码如下:

头文件

#ifndef _POOL_H#define _POOL_H#include "stdlib.h"#include "stdio.h"#include "string.h"#define LEN sizeof(memblock)//内存块节点大小#define OPERA_OK  0//操作失败#define OPERA_ERR 1//操作成功//内存块节点typedef struct MEMBLOCK{char* pmem;//内存指针 MEMBLOCK *next;//指向下一节点的指针}memblock;//内存池节点typedef struct MEMPOOL{int  cnt;//数量int  usedcnt;//使用个数int blocksize;//内存块大小char* firstaddr;//起始地址char* lastaddr;//结束地址MEMBLOCK *firstblock;//指向下一节点的指针}mempool;/*********************************************@brief 创建n个节点的内存池链表*@param*    num数量*    blocksize   内存块大小*@return OPERA_OK/OPERA_ERR*@see*********************************************/mempool *CreatePool(int num, int blocksize);/*********************************************@brief 销毁内存池*@param*    poolhead内存池指针*@return OPERA_OK/OPERA_ERR*@see*********************************************/int  DestroyPool(mempool  *poolhead);/*********************************************@brief  得到一个内存块*@param*    poolhead内存池指针*@return 内存块地址*@see*********************************************/char *GetMemblock(mempool *poolhead);/*********************************************@brief  释放一个内存块*@param* pmem内存块地址*    poolhead内存池指针*@return  OPERA_OK/OPERA_ERR*@see*********************************************/int ReleaseMemblock(char* pmem, mempool *poolhead);#endif
.c文件

#include "pool.h"/*********************************************@brief 创建n个节点的内存池链表*@param*    num数量*    blocksize   内存块大小*@return OPERA_OK/OPERA_ERR*@see*********************************************/ mempool *CreatePool(int num,int blocksize ){if(num<=0||blocksize<=0){printf("Create  input err\n");return NULL;}//内存池指针分配内存mempool *poolhead=NULL;//内存池指针poolhead=(mempool*)malloc(sizeof(mempool));//池节点申请内存if (NULL==poolhead){printf("poolhead malloc err!\n");return NULL;}memset(poolhead,0,sizeof(mempool));//内存池指针部分初始化赋值,其他默认为0无需初始poolhead->cnt=num;poolhead->blocksize=blocksize;//定义链表操作临时指针memblock *p1 = NULL;//创建的新节点的地址memblock *p2 = NULL;char* block;//内存块指针int n = 0;//创建前链表的节点总数为0:空链表//分配第一个内存块p1 = ( memblock *) malloc (LEN);//开辟第一个新节点if (NULL == p1){printf("p1 %d malloc err!\n",n+1);return NULL;}memset(p1,0,LEN);block=(char*)malloc(blocksize);//开辟内存块if (NULL == block){printf("firstblock malloc err!\n");return NULL;}memset(block,0,blocksize);//*内存池,内存块初始化赋值p1->pmem=block;poolhead->firstaddr=block; p2 = p1;//如果节点开辟成功,则p2先把它的指针保存下来以备后用if(p1==NULL)//节点开辟不成功{printf ("\nCann't create it, try it again in a moment!\n");return NULL;}while(n <num){n += 1;//节点总数增加1个if(n == 1)//如果节点总数是1,则head指向刚创建的节点p1{poolhead->firstblock = p1;p2->next = NULL;  //此时的p2就是p1,也就是p1->next指向NULL。}else{p2->next = p1;//指向上次下面刚刚开辟的新节点}p2 = p1;//把p1的地址给p2保留,然后p1产生新的节点p1 = ( memblock *) malloc (LEN);//开辟出新节点if (NULL == p1){printf("p1 %d malloc err!\n",n+1);return NULL;}memset(p1,0,LEN);block=(char*)malloc(blocksize);//开辟出新内存块if (NULL == block){printf("block %d malloc err!\n", n + 1);return NULL;}memset(block,0,blocksize);p1->pmem=block;}p2->next = NULL;//链表的最后一个节点指向NULLpoolhead->lastaddr=p2->pmem+blocksize;//内存池 末尾地址free(p1->pmem);free(p1);//跳出了while循环,释放p1   多余的那个空间p1 = NULL;return poolhead;    //返回创建链表的头指针 } /******************************************** *@brief 销毁内存池 *@param *    poolhead内存池指针 *@return OPERA_OK/OPERA_ERR *@see *********************************************/int  DestroyPool(mempool  *poolhead)  {  if(poolhead==NULL){return OPERA_ERR;}memblock  *p1=poolhead->firstblock;  memblock  *p2=p1;    while(p1!=NULL)      {          p2=p1;  p1=p1->next;  free(p2->pmem);p2->pmem=NULL;        free(p2);      }  poolhead->firstblock=NULL;free(poolhead);poolhead = NULL;return OPERA_OK;  } /*********************************************@brief  得到一个内存块*@param*    poolhead内存池指针*@return 内存块地址*@see*********************************************/char *GetMemblock(mempool *poolhead){if(poolhead->usedcnt==poolhead->cnt){printf("GetMemblock ERR !Pool Full!\n");return NULL;}if (poolhead==NULL||poolhead->firstblock==NULL){printf("pool in err!\n");return NULL;}memblock* p=poolhead->firstblock;poolhead->firstblock = p->next;p->next = NULL;poolhead->usedcnt++;return p->pmem;}/*********************************************@brief  释放一个内存块*@param* pmem内存块地址*    poolhead内存池指针*@return  OPERA_OK/OPERA_ERR*@see*********************************************/int ReleaseMemblock(char* pmem, mempool *poolhead){if(pmem==NULL){printf("Realease Mem input ERR!\n");return OPERA_ERR;}memblock *ptemp = (memblock *)malloc(LEN);if (NULL == ptemp){printf("ptemp malloc err!\n");return OPERA_ERR;}ptemp->pmem = pmem;ptemp->next=poolhead->firstblock;poolhead->firstblock = ptemp;poolhead->usedcnt--;return OPERA_OK;}

测试实例

#include "pool.h"int main(){int ret = OPERA_OK;mempool *pool = NULL;pool = CreatePool(3, 1024);//建立内存池if (pool == NULL){printf("Creat ERR!\n");}else{printf("Creat OK!\n");}printf("内存池信息 块数量%d,块大小%d,使用个数%d,起始地址0x%p,终止地址0x%p\n", pool->cnt, pool->blocksize, pool->usedcnt, pool->firstaddr, pool->lastaddr);char *Mem1 = GetMemblock(pool);printf("得到内存块地址0x%p\n", Mem1);printf("内存池信息 块数量%d,块大小%d,使用个数%d,起始地址0x%p,终止地址0x%p\n", pool->cnt, pool->blocksize, pool->usedcnt, pool->firstaddr, pool->lastaddr);char *Mem2 = GetMemblock(pool);printf("得到内存块地址0x%p\n", Mem2);printf("内存池信息 块数量%d,块大小%d,使用个数%d,起始地址0x%p,终止地址0x%p\n", pool->cnt, pool->blocksize, pool->usedcnt, pool->firstaddr, pool->lastaddr);char *Mem3 = GetMemblock(pool);printf("得到内存块地址0x%p\n", Mem3);printf("内存池信息 块数量%d,块大小%d,使用个数%d,起始地址0x%p,终止地址0x%p\n", pool->cnt, pool->blocksize, pool->usedcnt, pool->firstaddr, pool->lastaddr);char *Mem4 = GetMemblock(pool);printf("得到内存块地址0x%p\n", Mem4);printf("内存池信息 块数量%d,块大小%d,使用个数%d,起始地址0x%p,终止地址0x%p\n", pool->cnt, pool->blocksize, pool->usedcnt, pool->firstaddr, pool->lastaddr);ReleaseMemblock(Mem2, pool);printf("释放第二个内存块0x%p\n", Mem2);printf("内存池信息 块数量%d,块大小%d,使用个数%d,起始地址0x%p,终止地址0x%p\n", pool->cnt, pool->blocksize, pool->usedcnt, pool->firstaddr, pool->lastaddr);char *Mem5 = GetMemblock(pool);printf("得到内存块地址0x%p\n", Mem5);printf("内存池信息 块数量%d,块大小%d,使用个数%d,起始地址0x%p,终止地址0x%p\n", pool->cnt, pool->blocksize, pool->usedcnt, pool->firstaddr, pool->lastaddr);ret = DestroyPool(pool);//销毁内存池if (ret == OPERA_ERR){printf("Destory ERR!\n");}else{printf("Destroy OK!\n");}system("pause");return 0;}



0 0
原创粉丝点击