减少内存碎片,使服务器能长时间运行而不出现内存不够的情况
内存池使用场景1)一个连接一个内存池,连接存在时内存池只分配内存,不释放内存。连接断开时把整个内存池释放。(如果我们手写内存池,只推荐这种场景)
2)一个进程一个内存池,进程退出时才释放。这种情况不推荐手写,推荐使用谷歌的tcmalloc
内存分大块和小块,内存池先分配大块(node),再在大块中分配小块。内存池的一些状态本身也保存在大块之中。如果要分配的内存本来就是大块(large),则另行分配,全都存在一个链表中,
内存池的实现//注意mp_large_s 本身分配在node的数据块中
struct mp_large_s {
struct mp_large_s *next;
void *alloc;
};
struct mp_node_s {
unsigned char *last; //next free memory
unsigned char *end; //end of block (not inclusive)
struct mp_node_s *next;
size_t failed; // 内存分配失败的次数(失败很多次意味着很可能整块都用完了)
};
struct mp_pool_s {
size_t max;
struct mp_node_s *current;
struct mp_large_s large;
struct mp_node_s head[0]; //第一个node必须分配在pool之后的内存里
};
failed:当前节点分配内存失败的次数,越大则表示当前节点越有可能满
current:指向下一个最有可能有空余空间的节点,如果当前current节点的fail数大于一个阈值,则把current指向它的下一个节点
在分配块内存时注意以32字节对齐
#define MP_ALIGNMENT 32 #define mp_align(n, alignment) (((n)+(alignment-1)) & ~(alignment-1)) #define mp_align_ptr(p, alignment) (void *)((((size_t)p)+(alignment-1)) & ~(alignment-1))
以这种方式分配内存
struct mp_pool_s *p;
int ret = posix_memalign((void **)&p, MP_ALIGNMENT, size + sizeof(struct mp_pool_s) + sizeof(struct mp_node_s));
if (ret) {
return NULL;
}
接口
struct mp_pool_s *mp_create_pool(size_t size); void mp_destory_pool(struct mp_pool_s *pool); void *mp_alloc(struct mp_pool_s *pool, size_t size); void *mp_calloc(struct mp_pool_s *pool, size_t size); void mp_free(struct mp_pool_s *pool, void *p);具体实现
void *mp_alloc(struct mp_pool_s *pool, size_t size) {
unsigned char *m;
struct mp_node_s *p;
if (size <= pool->max) {
p = pool->current;
do {
m = mp_align_ptr(p->last, MP_ALIGNMENT);
if ((size_t)(p->end - m) >= size) {
p->last = m + size;
return m;
}
p = p->next;
} while (p);
return mp_alloc_block(pool, size);
}
return mp_alloc_large(pool, size);
}
其他函数略
参考资料零声教育c/c++ linux开发3.1.2



