用C语言写了个插件,在第三方服务器上跑。对方基于稳定、安全性等方面的考虑,提出了各种限制条件,其中有一个要求是程序运行期间,只允许申请一次内存空间。逼着只能自己实现一个内存池。
步骤1.程序启动时申请一块内存M;
步骤2.封装malloc函数,该函数实现申请的内存节点都从M内存块中划分;
步骤3.封装free函数,该函数实现将内存节点还给M内存块;
步骤4.为了避免内存节点碎片,释放后的小内存节点需要合并成一块。
相比直接调用malloc,有下面几点优点:
1.提升了性能,相对于malloc调用,性能提升了 不少
2.避免了系统内存碎片
3.避免了系统内存泄漏
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include "mpool.h"
static mpool_t s_mpool;
int mpool_init(size_t hold_size)
{
memset((void *)&s_mpool, 0, sizeof(s_mpool));
void *buffer = NULL;
buffer = (void *)malloc(hold_size*1024*1024);
if (NULL == buffer)
{
return B_FALSE;
}
s_mpool.hold_size = malloc_usable_size(buffer);
printf("[INIT] buffer = %p size = %x\n", buffer, s_mpool.hold_size);
mpool_alloc_node_t *head = (mpool_alloc_node_t *)buffer;
head->size = s_mpool.hold_size - sizeof(mpool_alloc_node_t);
head->start = buffer + sizeof(mpool_alloc_node_t);
head->alloc = 0;
head->next = NULL;
head->prev = NULL;
s_mpool.list.head = head;
s_mpool.list.tail = head;
s_mpool.free.head = head;
s_mpool.free.tail = head;
return B_TRUE;
}
static int del_node_from_free(mpool_alloc_node_t *node)
{
mpool_alloc_node_t *free = s_mpool.free.head;
while (NULL != free)
{
if (free == node)
{
if (node->prev == NULL)
{
s_mpool.free.head = node->next;
}else{
node->prev->next = node->next;
}
return B_TRUE;
}
free = free->next;
}
return B_FALSE;
}
static int del_node_from_list(mpool_alloc_node_t *node)
{
mpool_alloc_node_t *head = s_mpool.list.head;
while (NULL != head)
{
if (head == node)
{
if (node->prev == NULL)
{
s_mpool.list.head = node->next;
}else{
node->prev->next = node->next;
}
return B_TRUE;
}
head = head->next;
}
return B_FALSE;
}
static mpool_alloc_node_t *apply_free_node(size_t size)
{
printf("apply_free_node = %p\n", s_mpool.free.head);
mpool_alloc_node_t *node = s_mpool.free.head;
mpool_alloc_node_t *new_node = NULL;
while (NULL != node)
{
if (node->size > (size + sizeof(mpool_alloc_node_t)))
{
if ((node->size <= (size + 2*sizeof(mpool_alloc_node_t))))
{
del_node_from_free(node);
}else{
new_node = (mpool_alloc_node_t *)(node->start + size);
new_node->start = new_node + 1;
new_node->size = node->size - sizeof(mpool_alloc_node_t) - size;;
new_node->alloc = 0;
new_node->next = node->next;
new_node->prev = node->prev;
if (NULL == node->prev)
{
s_mpool.free.head = new_node;
}
printf("apply_free_node new_node %p\n", new_node);
node->next = new_node;
node->size = size;
}
node->alloc = 1;
printf("apply_free_node node %p\n", node);
return node;
}
node = node->next;
}
return NULL;
}
mpool_alloc_node_t *mpool_alloc_memory(size_t size)
{
mpool_alloc_node_t *node = apply_free_node(size);
if (NULL == node)
{
printf("Out of memory space\n");
}
#if 1
printf("find_free_node = %p headsize = %x start %p size %x\n", node, sizeof(mpool_alloc_node_t), node->start, node->size);
#endif
return node;
}
int mpool_free_node(mpool_alloc_node_t *node)
{
mpool_alloc_node_t *prev = node->prev;
mpool_alloc_node_t *next = node->next;
mpool_alloc_node_t *current = node;
while(NULL != current->prev)
{
current = current->prev;
if (0 == current->alloc)
{
current->size = current->size + node->size + sizeof(mpool_alloc_node_t);
current->next = node->next;
node->alloc = 0;
del_node_from_list(node);
return B_TRUE;
}
}
//head
if (NULL == prev)
{
s_mpool.free.head = node;
if (NULL != next)
{
if (0 == next->alloc)
{
node->size = node->size + next->size + sizeof(mpool_alloc_node_t);
node->next = next->next;
del_node_from_list(next);
}
}
}
node->alloc = 0;
return B_TRUE;
}
void print_pool(void)
{
mpool_alloc_node_t *node = s_mpool.list.head;
int i = 0;
while (NULL != node)
{
printf("[LIST]%d %p start = %p alloc = %d size = %x\n", i, node, node->start, node->alloc, node->size);
i++;
node = node->next;
}
}
void print_free(void)
{
mpool_alloc_node_t *node = s_mpool.free.head;
int i = 0;
while (NULL != node)
{
printf("[FREE]%d %p start = %p alloc = %d size = %x\n", i, node, node->start, node->alloc, node->size);
i++;
node = node->next;
}
}