为什么要使用内存池
- 避免反复申请和释放内存时出现的内存碎片;
- 防止内存泄漏;
- 提高申请和释放内存的效率。
结构
![01](https://i-blog.csdnimg.cn/blog_migrate/06a6e07ce086f5936cd8773c092f100d.png#pic_center)
代码
#ifndef MEMPOOL_H__
#define MEMPOOL_H__
#include <stdio.h>
#define MEMP_ALIGNMENT 32
#define MEMP_PAGE_SIZE 4096
#define MEMP_MAX_ALLOC_FROM_POOL (MEMP_PAGE_SIZE-1)
#define memp_align_ptr(p, alignment) \
(void *)((((size_t)p) + (alignment - 1)) & ~(alignment - 1))
typedef struct memp_large_st{
struct memp_large_st *next;
void *alloc;
}memp_large;
typedef struct memp_node_st{
struct memp_node_st *next;
unsigned char *last;
unsigned char *end;
}memp_node;
typedef struct memp_pool_st{
size_t max;
memp_node *current;
memp_large *large;
memp_node head[0];
}memp_pool;
memp_pool *memp_create_pool(size_t size);
void memp_destory_pool(memp_pool *pool);
void *memp_alloc(memp_pool *pool, size_t size);
void *memp_malloc(memp_pool *pool, size_t size);
void *memp_calloc(memp_pool *pool, size_t nitems, size_t size);
void memp_free(memp_pool *pool, void *ptr);
void memp_reset_pool(memp_pool *pool);
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "./mempool.h"
memp_pool *memp_create_pool(size_t size){
memp_pool *pool = NULL;
int res;
res = posix_memalign((void**)&pool, MEMP_ALIGNMENT, size+sizeof(*pool)+sizeof(memp_node));
if(res){
perror("posix_memalign()");
return NULL;
}
pool->max = size < MEMP_MAX_ALLOC_FROM_POOL ? size : MEMP_MAX_ALLOC_FROM_POOL;
pool->current = pool->head;
pool->large = NULL;
pool->head->last = (unsigned char*)pool + sizeof(memp_pool) + sizeof(memp_node);
pool->head->end = pool->head->last + size;
return pool;
}
void memp_destory_pool(memp_pool *pool){
memp_large *l;
memp_node *cur, *n;
for(l = pool->large; l; l = l->next){
if(l->alloc != NULL){
puts("free a large");
free(l->alloc);
}
}
cur = pool->head->next;
while(cur != NULL){
n = cur->next;
puts("free a block");
free(cur);
cur = n;
}
puts("free pool");
free(pool);
return ;
}
void *memp_alloc_large(memp_pool *pool, size_t size){
void *p = malloc(size);
if(p == NULL){
return NULL;
}
memp_large *large;
for(large = pool->large; large != NULL; large = large->next){
if(large->alloc == NULL){
large->alloc = p;
return p;
}
}
large = memp_alloc(pool, sizeof(memp_large));
if(large == NULL){
free(p);
return NULL;
}
large->alloc = p;
large->next = pool->large;
pool->large = large;
return p;
}
void *memp_alloc_block(memp_pool *pool, size_t size){
unsigned char *res = NULL;
memp_node *head = pool->head;
size_t alloc_size = (size_t)(head->end - (unsigned char*)head);
memp_node *new_node, *cur, *p;
int ret = 0;
ret = posix_memalign((void**)&res, MEMP_ALIGNMENT, alloc_size);
if(ret){
perror("posix_memalign()");
return NULL;
}
new_node = (memp_node*)res;
new_node->end = res + alloc_size;
new_node->next = NULL;
res += sizeof(memp_node);
res = memp_align_ptr(res, MEMP_ALIGNMENT);
new_node->last = res + size;
cur = pool->current;
for(p = cur; p->next != NULL; p = p->next){
;
}
p->next = new_node;
return res;
}
void *memp_alloc(memp_pool *pool, size_t size){
unsigned char *res = NULL;
memp_node *p = NULL;
if(size <= pool->max){
p = pool->current;
do{
res = memp_align_ptr(p->last, MEMP_ALIGNMENT);
if((size_t)(p->end - res) >= size){
p->last = res + size;
return res;
}
p = p->next;
}while(p != NULL);
return memp_alloc_block(pool, size);
}
return memp_alloc_large(pool, size);
}
void *memp_malloc(memp_pool *pool, size_t size){
unsigned char *res = NULL;
memp_node *p = NULL;
if(size <= pool->max){
p = pool->current;
do{
res = memp_align_ptr(p->last, MEMP_ALIGNMENT);
if((size_t)(p->end - res) >= size){
p->last = res + size;
return res;
}
p = p->next;
}while(p != NULL);
return memp_alloc_block(pool, size);
}
return memp_alloc_large(pool, size);
}
void *memp_calloc(memp_pool *pool, size_t nitems, size_t size){
size_t size_true = nitems * size;
void *res = memp_alloc(pool, size_true);
if(res != NULL){
memset(res, 0, size_true);
}
return res;
}
void memp_free(memp_pool *pool, void *ptr){
memp_large *large;
for(large = pool->large; large != NULL; large = large->next){
if(large->alloc == ptr){
free(large->alloc);
large->alloc = NULL;
break;
}
}
return ;
}
void memp_reset_pool(memp_pool *pool){
memp_node *head;
memp_large *large;
for(large = pool->large; large != NULL; large = large->next){
if(large->alloc != NULL){
free(large->alloc);
}
}
pool->large = NULL;
for(head = pool->head; head != NULL; head = head->next){
head->last = (unsigned char*)head + sizeof(memp_node);
}
return ;
}
#include <stdio.h>
#include <stdlib.h>
#include "./mempool.h"
int main(){
puts("hello world");
memp_pool *pool = NULL;
size_t size = 1 << 12;
pool = memp_create_pool(size);
char *ptr = NULL;
ptr = memp_alloc(pool, 1 << 13);
memp_free(pool, ptr);
ptr = memp_alloc(pool, 1 << 13);
memp_free(pool, ptr);
ptr = memp_alloc(pool, 1 << 13);
memp_free(pool, ptr);
ptr = memp_alloc(pool, 1 << 13);
fflush(stdout);
for(int i = 0; i < 10; i++){
ptr = memp_alloc(pool, 1 << 10);
}
for(int i = 0; i < 10; i++){
ptr = memp_malloc(pool, 1 << 11);
}
for(int i = 0; i < 10; i++){
ptr = memp_calloc(pool, 32, sizeof(long));
}
memp_destory_pool(pool);
exit(0);
}
待完善点
- 小块内存的重复使用:目前代码并没有释放小块内存的功能。可以等某一块中的所有小块内存都不使用时,直接释放这一大块内存。