内存池:简单的内存池的实现
疯狂代码 http://CrazyCoder.cn/ ĵ:http:/CrazyCoder.cn/VC/Article22433.html
当频繁地用malloc申请内存然后再用free释放内存时会存在两个主要问题第个问题是频繁分配释放内存可能导
致系统内存碎片过多;第 2个问题是分配释放内存花费时间可能比较多(这个问题不太明显)这个时候我们就可以
考虑使用内存池了
最朴素内存池思想就是首先你向系统申请块很大内存(这块内存很大以致于我们常称它为memory pool)然后你
在上面实现类似于malloc和free等操作当你需要分配内存时你用自己类malloc从内存池上取小块给使用者(后文
称的为小内存块)当用类free释放从内存池上取得内存时这个小内存块也并不归还给系统而只是还给内存池
最近写telnet还原写了个简易内存池和大家分享下
这个内存池提供这样功能:i)提供类mallocmem_alloc从内存池上获取固定大小内存提供类freemem_free释放
内存到内存池中;ii)内存池大小为某个固定大小(BUF_SIZE)n倍当内存池中内存不够用时内存池能以定步长增长
直到无系统内存
要实现这些功能首先应该用个数据结构(mem_node_t)将内存池中各个小内存块挂起来;然后为了使内存池能
够以定步长增长我们要能分配多个大内存块(即多个小内存池)为了能顺利管理各个大内存块需要个数据结构
(mem_block_t)来记录这些信息;最后内存池当前状态(包括可分配空闲链表空闲小内存块个数等)是我们感兴趣
东西所以用数据结构(mem_pool_t)来记录
typedef union _mem_node
{
union _mem_node *next;
char buf[BUF_SIZE];
}mem_node_t, *pmem_node_t;
typedef struct _mem_block
{
mem_node_t *node_head; /* 第个小内存块 */
mem_node_t *node_tail; /* 最后个小内存块 */
node_cnt; /* node count */
struct _mem_block *next;
}mem_block_t, *pmem_block_t;
typedef struct _mem_pool
{
mem_block_t *block_head; /* 第个大内存块 */
mem_block_t *block_tail; /* 最后个大内存块 */
mem_node_t *free_head; /* 当前空闲链表头指针 */
block_cnt; /* block count */
free_cnt; /* free node count; */
base; /* 内存池大小 */
step; /* 内存池增长步长 */
}mem_pool_t, *pmem_pool_t;
然后提供了些操作:mem_pool_init用来化内存池;mem_pool_destroy用来释放内存池将内存池所占空间归还
系统;pr_mem_pool_info用来打印内存池信息;mem_alloc用来从内存池上分配小内存块;mem_free将小
内存块归还给内存池
mem_alloc和mem_free操作就是内存池空闲链表前者从空闲链表取个结点后者将个结点插入空闲链表而这个
空闲链表是由mem_pool_init化而且当内存池增长时即增加新大内存块时我们将大内存块上小内存块也挂接到
这个空闲链表上来需要注意是小内存块数据结构用了联合这是小内存块要么是挂接在空闲链表上要么是分配给
了用户必居且只能居这两种状态的,这个数据结构可根据需求适当改进
在码代码的前要补充介绍说明是不少内存池都提供了分配区别大小内存块功能将多个区别大小本内存池链接起
来也可实现这些功能改动是比较容易^_^
最后本内存池在vc6下验证当频繁分配释放100字节大小内存时本内存池效率约是直接malloc和free10倍当分配
大小变小时效率比有所降低但当分配大小增大时效率比有所升高分配1000字节大小内存时效率比约为100
代码
/************************mem_pool.h************************
*author:bripengandre
*
**********************************************************/
#ndef _MEM_POOL_H_
# _MEM_POOL_H_
# BUF_SIZE 100
# BASE_COUNT 10000
# STEP_COUNT 1000
/* #pragma pack */
/* */
typedef union _mem_node
{
union _mem_node *next;
char buf[BUF_SIZE];
}mem_node_t, *pmem_node_t;
/* used to store block information */
typedef struct _mem_block
{
mem_node_t *node_head;
mem_node_t *node_tail;
node_cnt; /* node count */
struct _mem_block *next;
}mem_block_t, *pmem_block_t;
/* used to store the pool information */
typedef struct _mem_pool
{
mem_block_t *block_head;
mem_block_t *block_tail;
mem_node_t *free_head;
block_cnt; /* block count */
free_cnt; /* free node count; */
base;
step;
}mem_pool_t, *pmem_pool_t;
/* mem_pool will have at least base blocks, and will increase steps a time needed */
mem_pool_init( base, step);
void mem_pool_destroy(void);
void pr_mem_pool_info(void);
/* since the block size is constant, this function need no input parameter */
void *mem_alloc(void);
void mem_free(void *ptr);
#end /* _MEM_POOL_H */
/************************mem_pool.c************************
*author:bripengandre
*
**********************************************************/
# "mem_pool.h"
#
# <.h>
#
# MEM_POOL_DEBUG
/* add memory block to our memory pool */
add_mem_block( cnt);
/* init the block */
mem_block_init( cnt, mem_block_t *block);
/* init free_list of the block */
free_list_init(const mem_block_t *block);
mem_pool_t mem_pool;
/* mem_pool will have at least base blocks, and will increase steps a time needed */
mem_pool_init( base, step)
{
(base <= 0)
{
base = BASE_COUNT;
}
(step <= 0)
{
step = STEP_COUNT;
}
/* initiate mem_pool */
mem(&mem_pool, 0, (mem_pool));
mem_pool.base = base;
mem_pool.step = step;
/* add the base block(node of base count) o the memory pool */
(!add_mem_block(base))
{
fprf(stderr, "mem_pool_init::add_mem_block error\n");
0;
}
1;
}
void mem_pool_destroy(void)