头文件:mem_palloc.h
#ifndef _MEM_PALLOC_H_INCLUDED_
#define _MEM_PALLOC_H_INCLUDED_
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <malloc.h>
#include <stdint.h>
typedef unsigned char u_char;
typedef intptr_t mem_int_t;
typedef uintptr_t mem_uint_t;
typedef intptr_t mem_flag_t;
typedef void (*mem_pool_cleanup_pt)(void *data);
typedef struct mem_pool_s mem_pool_t;
typedef struct mem_pool_large_s mem_pool_large_t;
typedef struct mem_pool_cleanup_s mem_pool_cleanup_t;
/********************************************************
* global var
* *****************************************************/
mem_uint_t mem_pagesize;
#ifndef MEX_ALIGNMENT
#define MEM_ALIGNMENT sizeof(unsigned long) /* platform word */
#endif
#define mem_free free
#define MEM_MAX_ALLOC_FROM_POOL (mem_pagesize - 1)
#define MEM_DEFAULT_POOL_SIZE (16 * 1024)
#define MEM_POOL_ALIGNMENT 16
#define MEM_MIN_POOL_SIZE \
mem_align((sizeof(mem_pool_t) + 2 * sizeof(mem_pool_large_t)), \
MEM_POOL_ALIGNMENT)
#define mem_align(d, a) (((d) + (a - 1)) & ~(a - 1))
#define mem_align_ptr(p, a) \
(u_char *) (((uintptr_t) (p) + ((uintptr_t) a - 1)) & ~((uintptr_t) a - 1))
/*****************************************************************/
typedef struct {
u_char *last; //当前内存池分配到此处,即下一次分配从此处开始
u_char *end; //内存池的结束位置
mem_pool_t *next; //内存池可以有很多块内存,这些内存块链表指针
mem_uint_t failed; //分配失败次数
} mem_pool_data_t;
struct mem_pool_s {
mem_pool_data_t d; //内存池数据块
size_t max; //内存池数据块的最大值
mem_pool_t *current; //当前内存池的地址
mem_pool_large_t *large; //大块内存链表
mem_pool_cleanup_t *cleanup; //释放内存池的回调
};
struct mem_pool_large_s {
mem_pool_large_t *next; //大块内存链表指针
void *alloc; //大块内存申请到的地址
};
struct mem_pool_cleanup_s {
mem_pool_cleanup_pt handler;
void *data;
mem_pool_cleanup_t *next;
};
void *mem_alloc(size_t size); //为大块内存申请内存
void *mem_palloc(mem_pool_t *pool, size_t size); //从内存池申请内存
void *mem_memalign(size_t alignment, size_t size); //分配对齐的内存
mem_pool_t *mem_create_pool(size_t size); //创建内存池
void mem_destroy_pool(mem_pool_t *pool); //释放内存池
#endif /*_MEM_PALLOC_H_INCLUDED_*/
内存池接口实现c文件:mem_palloc.c
#include "mem_palloc.h"
void mem_os_init(void)
{
mem_pagesize = getpagesize(); //获取pagesize到全局变量mem_pagesize
}
void *mem_alloc(size_t size)
{
void *p;
p = malloc(size);
if (p == NULL) {
fprintf(stderr, "malloc(%uz) failed\n", size);
}
printf("malloc: %p:%uz\n", p, size);
return p;
}
//申请新的数据块
static void * mem_palloc_block(mem_pool_t *pool, size_t size)
{
u_char *m;
size_t psize;
mem_pool_t *p, *new, *current;
psize = (size_t)(pool->d.end - (u_char *)pool);
m = mem_memalign(MEM_POOL_ALIGNMENT, psize);
if (m == NULL) {
return NULL;
}
new = (mem_pool_t *)m;
new->d.end = m + psize;
new->d.next = NULL;
new->d.failed = 0;
m += sizeof(mem_pool_data_t);
m = mem_align_ptr(m, MEM_ALIGNMENT);
new->d.last = m + size;
current = pool->current;
for (p = current; p->d.next; p = p->d.next) {
if (p->d.failed++ > 4) {
current = p->d.next;
}
}
p->d.next = new;
pool->current = current ? current : new;
return m;
}
//申请大块内存
static void *mem_palloc_large(mem_pool_t *pool, size_t size)
{
void *p;
mem_uint_t n;
mem_pool_large_t *large;
p = mem_alloc(size);
if (p == NULL) {
return NULL;
}
n = 0;
for (large = pool->large; large; large = large->next) {
if (large->alloc == NULL) {
large->alloc = p;
return p;
}
if (n++ > 3) {
break;
}
}
large = mem_palloc(pool, sizeof(mem_pool_large_t));
if (large == NULL) {
mem_free(p);
return NULL;
}
large->alloc = p;
large->next = pool->large;
pool->large = large;
return p;
}
//从内存池申请size大小的内存
void *mem_palloc(mem_pool_t *pool, size_t size)
{
u_char *m;
mem_pool_t *p;
if (size <= pool->max) {
p = pool->current;
do {
m = mem_align_ptr(p->d.last, MEM_ALIGNMENT);
if ((size_t)(p->d.end - m) >= size) {
p->d.last = m + size;
return m;
}
p = p->d.next;
} while (p);
return mem_palloc_block(pool, size);
}
return mem_palloc_large(pool, size);
}
void *mem_memalign(size_t alignment, size_t size)
{
void *p;
p = memalign(alignment, size);
if (p == NULL) {
fprintf(stderr, "memalign(%uz, %uz) failed\n", alignment, size);
}
printf("memalign: %p:%uz @%uz\n", p, size, alignment);
return p;
}
mem_pool_t *mem_create_pool(size_t size)
{
mem_pool_t *p;
p = mem_memalign(MEM_POOL_ALIGNMENT, size);
if (p == NULL) {
return NULL;
}
p->d.last = (u_char *)p + sizeof(mem_pool_t);
p->d.end = (u_char *)p + size;
p->d.next = NULL;
p->d.failed = 0;
size = size - sizeof(mem_pool_t);
p->max = (size < MEM_MAX_ALLOC_FROM_POOL) ? size : MEM_MAX_ALLOC_FROM_POOL;
p->current = p;
p->large = NULL;
p->cleanup = NULL;
return p;
}
void mem_destroy_pool(mem_pool_t *pool)
{
mem_pool_t *p, *n;
mem_pool_large_t *l;
mem_pool_cleanup_t *c;
for (c = pool->cleanup; c; c = c->next) {
if (c->handler) {
c->handler(c->data);
}
}
for (l = pool->large; l; l = l->next) {
if (l->alloc) {
mem_free(l->alloc);
}
}
for (p = pool, n = pool->d.next; /* void */; p = n, n = n->d.next) {
mem_free(p);
if (n == NULL) {
break;
}
}
}
测试c文件:main.c
#include "mem_palloc.h"
void dump_pool(mem_pool_t* pool)
{
while (pool)
{
printf("pool = 0x%x\n", pool);
printf(" .d\n");
printf(" .last = 0x%x\n", pool->d.last);
printf(" .end = 0x%x\n", pool->d.end);
printf(" .next = 0x%x\n", pool->d.next);
printf(" .failed = %d\n", pool->d.failed);
printf(" .max = %d\n", pool->max);
printf(" .current = 0x%x\n", pool->current);
printf(" .large = 0x%x\n", pool->large);
printf(" .cleanup = 0x%x\n", pool->cleanup);
printf("available pool memory = %d\n\n", pool->d.end - pool->d.last);
pool = pool->d.next;
}
}
int main(int argc, char *argv[])
{
mem_pool_t *pool;
printf("--------------------------------\n");
printf("create a new pool:\n");
printf("--------------------------------\n");
pool = mem_create_pool(1024);
dump_pool(pool);
printf("--------------------------------\n");
printf("alloc block 1 from the pool:\n");
printf("--------------------------------\n");
mem_palloc(pool, 512);
dump_pool(pool);
printf("--------------------------------\n");
printf("alloc block 2 from the pool:\n");
printf("--------------------------------\n");
mem_palloc(pool, 512);
dump_pool(pool);
printf("--------------------------------\n");
printf("alloc block 3 from the pool :\n");
printf("--------------------------------\n");
mem_palloc(pool, 512);
dump_pool(pool);
mem_destroy_pool(pool);
return 0;
}
Makefile文件:
CC=gcc
CFLAGS=-Wall -std=c99 -pedantic
EXEC=mem_pool_test
OBJETCS= main.o mem_palloc.o
all: mem_pool_test
mem_pool_test: $(OBJETCS)
$(CC) $(CFLAGS) $(OBJETCS) -o mem_pool_test
main.o: main.c mem_palloc.h
$(CC) $(CFLAGS) -c main.c -o main.o
mem_palloc.o: mem_palloc.c mem_palloc.h
$(CC) $(CFLAGS) -c mem_palloc.c -o mem_palloc.o
clean:
rm -f $(EXEC) *.o *~
运行结果:
[nginx@localhost mempool]$ ./mem_pool_test
--------------------------------
create a new pool:
--------------------------------
memalign: 0x143f010:1024 @16
pool = 0x143f010
.d
.last = 0x143f050
.end = 0x143f410
.next = 0x0
.failed = 0
.max = 960
.current = 0x143f010
.large = 0x0
.cleanup = 0x0
available pool memory = 960
--------------------------------
alloc block 1 from the pool:
--------------------------------
pool = 0x143f010
.d
.last = 0x143f250
.end = 0x143f410
.next = 0x0
.failed = 0
.max = 960
.current = 0x143f010
.large = 0x0
.cleanup = 0x0
available pool memory = 448
--------------------------------
alloc block 2 from the pool:
--------------------------------
memalign: 0x143f420:1024 @16
pool = 0x143f010
.d
.last = 0x143f250
.end = 0x143f410
.next = 0x143f420
.failed = 0
.max = 960
.current = 0x143f010
.large = 0x0
.cleanup = 0x0
available pool memory = 448
pool = 0x143f420
.d
.last = 0x143f640
.end = 0x143f820
.next = 0x0
.failed = 0
.max = 0
.current = 0x0
.large = 0x0
.cleanup = 0x0
available pool memory = 480
--------------------------------
alloc block 3 from the pool :
--------------------------------
memalign: 0x143f830:1024 @16
pool = 0x143f010
.d
.last = 0x143f250
.end = 0x143f410
.next = 0x143f420
.failed = 1
.max = 960
.current = 0x143f010
.large = 0x0
.cleanup = 0x0
available pool memory = 448
pool = 0x143f420
.d
.last = 0x143f640
.end = 0x143f820
.next = 0x143f830
.failed = 0
.max = 0
.current = 0x0
.large = 0x0
.cleanup = 0x0
available pool memory = 480
pool = 0x143f830
.d
.last = 0x143fa50
.end = 0x143fc30
.next = 0x0
.failed = 0
.max = 0
.current = 0x0
.large = 0x0
.cleanup = 0x0
available pool memory = 480
致谢:
参考了博主阿波321的博客https://blog.csdn.net/livelylittlefish/article/details/6586946