Chinaunix首页 | 论坛 | 博客
  • 博客访问: 192079
  • 博文数量: 40
  • 博客积分: 2265
  • 博客等级: 大尉
  • 技术积分: 434
  • 用 户 组: 普通用户
  • 注册时间: 2010-08-23 17:01
文章分类

全部博文(40)

文章存档

2014年(1)

2013年(2)

2012年(6)

2011年(5)

2010年(26)

我的朋友

分类: LINUX

2010-12-23 19:36:42

内存池实现相当的简单,由两个个主要部分组成 pheap,pfree,pool_struct,以及基本的内存池API

pheap:         内存块,它由pfree组织管理
pfree:          由pheap构成链表,它作为内存池实体单元
pool_struct: 内存池结构体
 
//pool.h文件
//=========================================================================
//于内存池中的实体(内存块)关联的回调函数,当实体释放时调用
typedef void (*pool_cleanup_t)(void *arg);
//单独内存分块
struct pheap
{
void *block; //实际的数据内存块
int size,used; //实际大小,使用大小
};
//带有释放内存毁掉函数的内存分块链表结点(内存池实体)
struct pfree

pool_cleanup_t f; 
//内存释放毁掉函数
void *arg; 
struct pheap *heap; //单独内存分块
struct pfree *next; //下一个单独内存分块
};

//内存池--基于内存池实体。管理一个由内存池实体(pfree)组成的链表。
typedef struct pool_struct
{
int size; //内存池大小
struct pfree *cleanup; //链表首结点
struct pfree *cleanup_tail; //链表尾结点
struct pheap *heap; 
#ifdef POOL_DEBUG 
//调试信息
char name[8], zone[32];
int lsize;
#endif
} _pool, 
*pool_t;

#ifdef POOL_DEBUG 
//调式调用函数版本定义宏
# define pool_new() _pool_new(__FILE__,__LINE__) 
# define pool_heap(i) _pool_new_heap(i,__FILE__,__LINE__) 
#else
# define pool_heap(i) _pool_new_heap(i,NULL,
0
# define pool_new() _pool_new(NULL,
0)
#endif

//jabberd2内存池API函数定义
JABBERD2_API pool_t _pool_new(char *file, int line); //构建一个新的内存池
JABBERD2_API pool_t _pool_new_heap(int size, char *file, int line); //构建一个指定初始内存区块大小的内存池
JABBERD2_API void *pmalloc(pool_t, int size);//封装 malloc函数,内存从内存池中进行分配,自动完成释放
JABBERD2_API void *pmalloc_x(pool_t p, int size, char c); /* Wrapper around pmalloc which prefils buffer with c */
JABBERD2_API 
void *pmalloco(pool_t p, int size); /* YAPW for zeroing the block */
JABBERD2_API 
char *pstrdup(pool_t p, const char *src); /* wrapper around strdup, gains mem from pool */
JABBERD2_API 
char *pstrdupx(pool_t p, const char *src, int len); /* use given len */
JABBERD2_API 
void pool_stat(int full); /* print to stderr the changed pools and reset */
JABBERD2_API 
void pool_cleanup(pool_t p, pool_cleanup_t fn, void *arg); /* calls f(arg) before the pool is freed during cleanup */
JABBERD2_API 
void pool_free(pool_t p);//调用所有的内存释放回调函数,释放所有内存池中的数据,删除内存池本身
JABBERD2_API int pool_size(pool_t p); //返回内存中已分配的总字节数

 

//pool.c文件
//=========================================================================

//构建一个新的空内存池
pool_t _pool_new(char *zone, int line)
{
pool_t p; 
while((p = _pool__malloc(sizeof(_pool))) == NULL) sleep(1);
p
->cleanup = NULL; //初始空链表
p->heap = NULL; //同上
p->size = 0

#ifdef POOL_DEBUG
p
->lsize = -1;
p
->zone[0= '\0';
snprintf(p
->zone, sizeof(p->zone), "%s:%i", zone, line);
sprintf(p
->name,"%X",(int)p);

if(pool__disturbed == NULL)
{
pool__disturbed 
= (xht)1/* reentrancy flag! */
pool__disturbed 
= xhash_new(POOL_NUM);
}
if(pool__disturbed != (xht)1)
xhash_put(pool__disturbed,p
->name,p);
#endif

return p;
}

//释放一个内存分块
static void _pool_heap_free(void *arg)
{
struct pheap *= (struct pheap *)arg;

_pool__free(h
->block); //free数据内存块
_pool__free(h); //free pheap结构体自身
}

//向内存池中添加内存池实体pfree
static void _pool_cleanup_append(pool_t p, struct pfree *pf)
{
struct pfree *cur;

if(p->cleanup == NULL)//空内存池时
{
p
->cleanup = pf;
p
->cleanup_tail = pf;
return;
}

//链表末尾添加新实体
cur = p->cleanup_tail; 
cur
->next = pf;
p
->cleanup_tail = pf;
}

//创建一个内存池实体
static struct pfree *_pool_free(pool_t p, pool_cleanup_t f, void *arg)
{
struct pfree *ret;

//为内存池实体分配内存
while((ret = _pool__malloc(sizeof(struct pfree))) == NULL) sleep(1);
ret
->= f; //内存块释放回调函数
ret->arg = arg; //回调函数参数
ret->next = NULL;

return ret;
}
//创建一个内存块,并为其设置内存释放回调函数
static struct pheap *_pool_heap(pool_t p, int size)
{
struct pheap *ret; //数据内存块结构体
struct pfree *clean; //内存池实体

//分配内存数据块结构体内存
while((ret = _pool__malloc(sizeof(struct pheap))) == NULL) sleep(1); 
//分配数据内存块内存
while((ret->block = _pool__malloc(size)) == NULL) sleep(1);
ret
->size = size; //指定数据内存块大小
p->size += size; //更新内存池总字节数
ret->used = 0

//生成对应的内存池实体,_pool_heap_free为静态函数地址,ret为其调用参数
clean = _pool_free(p, _pool_heap_free, (void *)ret);
clean
->heap = ret; /* for future use in finding used mem for pstrdup */
_pool_cleanup_append(p, clean);
//将内存池实体,添加到内存池实体链表中

return ret;
}

//内存池内存请求函数
void *pmalloc(pool_t p, int size)
{
void *block;

if(p == NULL)
{
fprintf(stderr,
"Memory Leak! [pmalloc received NULL pool, unable to track allocation, exiting]\n");
abort();
}

//如果内存池中没有可用内存,或者申请的内存过大时,直接从进程堆中申请内存
if(p->heap == NULL || size > (p->heap->size / 2))

while((block = _pool__malloc(size)) == NULL) sleep(1); //直接从进程内存堆上分配
p->size += size; //递增内存池总字节数
_pool_cleanup_append(p, _pool_free(p, _pool__free, block));//生成相应的内存池实体,并添加到内存池实体链表中
return block;
}

/* we have to preserve boundaries, long story :) */
if(size >= 4)
while(p->heap->used&7) p->heap->used++;

/* if we don't fit in the old heap, replace it */
// 如果在现有内存块中没有足够的内存,重新申请一块
if(size > (p->heap->size - p->heap->used))
p
->heap = _pool_heap(p, p->heap->size);

//当前内存块有剩余空间
block = (char *)p->heap->block + p->heap->used; //返回内存区块有效地址
p->heap->used += size; //更新内存区块使用情况
return block;

}

//对pmalloc进行封装并使用参数c的内容预填充新内存块
void *pmalloc_x(pool_t p, int size, char c)
{
void* result = pmalloc(p, size);
if (result != NULL)
memset(result, c, size);
return result;



//方便,安全(为结构体申请空白内存等)
void *pmalloco(pool_t p, int size)
{
void *block = pmalloc(p, size);
memset(block, 
0, size);
return block;
}
阅读(1305) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2010-12-26 17:27:33

很好的, 收藏了 推荐一个博客,提供很多免费软件编程电子书下载: http://free-ebooks.appspot.com