一个简单的变长内存池
#define NODE_SIZE (200) //每个node的大小
#define BASE_NODE_NUM (1024 * 1) //初始分配大小
#define STEP_NODE_NUM (1024 * 1) //每次递增大小
#include <string.h>
#pragma pack(1)
typedef struct _mem_node
{
unsigned int num; //每次分配的内存区域的个数
union
{
struct _mem_node *next;
char buf[NODE_SIZE]; //每个node的大小
};
_mem_node()
{
num = 0;
memset(buf,0,sizeof(buf));
};
}mem_node_t, *pmem_node_t;
#pragma pack()
/* block信息*/
typedef struct _mem_block
{
mem_node_t *node_head;
mem_node_t *node_tail;
unsigned int node_num; // block中node个数
struct _mem_block *next; //用于将每个block连接起来
}mem_block_t, *pmem_block_t;
/*pool信息*/
typedef struct _mem_pool
{
mem_block_t* block_head; //第一个block
mem_block_t* block_tail; //最后一个block
mem_node_t* free_head; //空闲节点
unsigned int block_num; //block个数
unsigned int free_num; //空闲节点个数
unsigned int base_num; //初始内存节点个数
unsigned int step_num; //每次内存增长节点个数
}mem_pool_t, *pmem_pool_t;
int InitMemPool(int base, int step); //初始化内存池
void DestroyMemPool(void); //销毁内存池
void* AllocMem(unsigned int size); //分配内存
void FreeMem(void* ptr); //销毁内存
#include "MemoryTest.h"
#include "stdio.h"
#include <string.h>
#include <stdlib.h>
#include <math.h>
#define MEM_POOL_DEBUG
/*add new memory block to our memory pool*/
static int AddMemBlock(int num);
/* init the new block */
static int InitMemBlock(int num, mem_block_t *block);
/* init free_list of the new block */
static int InitFreeList(const mem_block_t *block);
void print_mem_pool_info(void);
//int mem_block_init(int base, int step);
static mem_pool_t mem_pool;
/* mem_pool will have at least base blocks,
and will increase steps a time if needed */
int InitMemPool(int base_num, int step_num)
{
/* initiate mem_pool */
memset(&mem_pool, 0, sizeof(mem_pool));
mem_pool.base_num = base_num;
mem_pool.step_num = step_num;
/* add the base block(node of base count) into the memory pool */
if(!AddMemBlock(base_num))
{
fprintf(stderr, "mem_pool_init::add_mem_block error/n");
return 0;
}
return 1;
}
void DestroyMemPool(void)
{
mem_block_t *prev, *cur;
prev = NULL;
cur = mem_pool.block_head;
while(prev != NULL)
{
prev = cur;
cur = cur->next;
free(cur->node_head); //逐个block中的node。
free(prev); //释放block自身
}
memset(&mem_pool, 0, sizeof(mem_pool_t));
}
void print_mem_pool_info(void)
{
int i;
mem_block_t *p;
if(mem_pool.block_head == NULL)
{
fprintf(stderr, "memory pool has been created!
");
return;
}
printf("*************** memory pool information start ***********************
");
printf("block count: %4d
", mem_pool.block_num);
printf("current free node count: %4d
", mem_pool.free_num);
printf("base block size: %4d
", mem_pool.base_num);
printf("increasing block size: %4d
", mem_pool.step_num);
printf("the first block: %#x
", mem_pool.block_head);
printf("the last block: %#x
", mem_pool.block_tail);
printf("the first free node: %#x
", mem_pool.free_head);
for(p = mem_pool.block_head, i = 0; p != NULL; p = p->next, i++)
{
printf("-------------------block %4d--------------------------
", i+1);
printf("node count: %4d
", p->node_num);
printf("the first node: %#x
", p->node_head);
printf("the last node: %#x
", p->node_tail);
printf("------------------------------------------------------
");
}
printf("***** memory pool information end ****
");
}
/* since the block size is constant, this function need no input parameter */
void* AllocMem(unsigned int size)
{
mem_node_t *p;
int num = (int)ceil((double)size / NODE_SIZE); //获得需要分配的节点数。
/* no free node ready, attempt to allocate new free node */
if(mem_pool.free_num < num)
{
if(!AddMemBlock(mem_pool.step_num))
{
return NULL;
}
}
/* get free node from free_list */
p = mem_pool.free_head;
p->num = num;
mem_pool.free_head = ((mem_node_t*)(p + num - 1))->next;
/* decrease the free node count */
mem_pool.free_num = mem_pool.free_num - num;
return p->buf;
}
void FreeMem(void *ptr)
{
mem_node_t* temp_node = (mem_node_t*)((char*)ptr - 4);
if(ptr == NULL)
{
return;
}
int num = temp_node->num;
/* return the node to free_list */
((mem_node_t*)(temp_node + num - 1))->next = mem_pool.free_head; //插入到空闲链表头部
mem_pool.free_head = temp_node;
/* increase the free node count */
mem_pool.free_num = mem_pool.free_num + num;
}
/* add new memory block to our memory pool */
static int AddMemBlock(int num)
{
mem_block_t *block;
if( (block = (mem_block_t *)malloc(sizeof(mem_block_t))) == NULL)
{
fprintf(stderr, "add_mem_block::malloc error/n");
return 0;
}
memset(block, 0, sizeof(mem_block_t));
if(!InitMemBlock(num, block))
{
fprintf(stderr, "mem_pool_init::mem_block_init error/n");
return 0;
}
/* insert the new block in the head */
block->next = mem_pool.block_head; //采用前插法
mem_pool.block_head = block;
if(mem_pool.block_tail == NULL)
{
mem_pool.block_tail = block;
}
/* insert the new block into the free list */
block->node_tail->next = mem_pool.free_head;
mem_pool.free_head = block->node_head; //所有空闲的node链接起来,也是采用前插入法
mem_pool.free_num += num;
/* increase the block count */
mem_pool.block_num++;
return 1;
}
/* init the new block */
static int InitMemBlock(int num, mem_block_t *block)
{
int block_size;
mem_node_t* temp_node;
if(block == NULL)
{
return 0;
}
block_size = num * sizeof(mem_node_t);
if( (temp_node = (mem_node_t *)malloc(block_size)) == NULL)
{
fprintf(stderr, "mem_pool_init::malloc error/n");
return 0;
}
memset(temp_node, 0, block_size);
memset(block, 0, sizeof(mem_block_t));
block->node_num = num;
block->node_head = temp_node;
block->node_tail = temp_node + num - 1;
InitFreeList(block);
return 1;
}
/* init free_list of the new block */
static int InitFreeList(const mem_block_t *block)
{
mem_node_t *temp_node, *end;
if(block == NULL)
{
return 0;
}
/* start initiating free list */
end = block->node_tail; /* block_cnt > 0 */
for(temp_node = block->node_head; temp_node < end; temp_node++)
{
temp_node->next = (temp_node + 1);
}
temp_node->next = NULL; /* end->next = NULL */
return 1;
}
#ifdef MEM_POOL_DEBUG
#define ALLOC_COUNT 10
void alloc_test(char *ptr[])
{
int i, j;
for(i = 0; i < ALLOC_COUNT; i++)
{
if( (ptr[i] = (char*)AllocMem(200)) == NULL)
{
fprintf(stderr, "mem_alloc error
");
return;
}
for(j = 0; j < ALLOC_COUNT; j++)
{
ptr[i][j] = "a" + j;
}
}
for(i = 0; i < ALLOC_COUNT; i++)
{
for(j = 0; j < ALLOC_COUNT; j++)
{
printf("ptr[%d][%d]=%c ", i, j, ptr[i][j]);
}
fputc("
", stdout);
}
}
int main(int argc, char *argv[])
{
char *ptr1[ALLOC_COUNT], *ptr2[ALLOC_COUNT];
printf("size = %d",sizeof(mem_node_t));
if(!InitMemPool(BASE_NODE_NUM, STEP_NODE_NUM))
{
fprintf(stderr, "mem_pool_init error/n");
return 1;
}
print_mem_pool_info();
alloc_test(ptr1);
print_mem_pool_info();
FreeMem((void*)ptr1[5]);
print_mem_pool_info();
alloc_test(ptr2);
print_mem_pool_info();
DestroyMemPool();
if(!InitMemPool(BASE_NODE_NUM, STEP_NODE_NUM))
{
fprintf(stderr, "mem_pool_init error/n");
return 1;
}
print_mem_pool_info();
alloc_test(ptr1);
print_mem_pool_info();
FreeMem(ptr1[5]);
print_mem_pool_info();
alloc_test(ptr2);
print_mem_pool_info();
DestroyMemPool();
return 1;
}
#endif /* #ifdef MEM_POOL_DEBUG */声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。
- 上一篇: C51学习笔记
- 下一篇: C51简介及Keil的使用
