内存池是对堆进行管理
当进程执行时,操作系统会分出0~4G的虚拟内存空间给进程,程序员可以自行管理(分配、释放)的部分就是mmap映射区、heap堆区,而内存池管理的部分就是用户进程的堆区。
为什么要用内存池?
内存池就是用来避免堆区出现碎片化
-
避免频繁地分配和释放内存(防止堆区出现碎片化)
当客户端连接上服务端的时候,服务端会准备一部分的堆区用来做消息保留。当一个连接成功之后,服务器会在堆区为其分配一段属于这个连接的内存,当连接关闭之后,所分配的内存也随之释放。但是当连接量较大且过于频繁时,不可避免地对内存进行频繁的分配和释放。这会导致堆区出现小窗口,也就是堆区碎片化。
堆区出现碎片化会怎么样?
-
长时间工作会出现不可查的BUG
-
无法分配较大且整块的内存,malloc会返回NULL
内存池设计
场景:在一段很干净的堆区上,如何实现能避免内存碎片化的内存池?
第一:使用链表管理内存
使用链表将分配出来的一块一块内存在堆区连接起来,设置flag(是否被使用),让链表节点上的各段内存慢慢各自扩张。
单独使用链表会出现什么问题?
-
内存块会被划分得越来越小,链表会变得越来越长,知道不能划分出更大得内存。
所以加入了固定内存的想法的设计
对于分配小段内存时,将小段内存进行固定划分,如下
-
16bytes
-
32bytes
-
64bytes
-
128bytes
-
256byts
-
512bytes
但是不同的固定小内存的分配的话就会出现以下问题:
1.查找慢
分配时查找
释放时候查找
2.块与块之间也会出现间隙
无法将块合并
小块回收麻烦
所以最后得出自定义固定小块和随机大块的内存池模型
内存池
内存池工作流程

内存池结构体
//内存池
struct mp_pool_s{
size_t max;
struct mp_node_s *current; //当前指向的小块内存区,链表结构
struct mp_large_s *large; //大块内存
struct mp_node_s *head[0]; //小块内存的头部
};