首页 > 代码库 > dlmalloc 2.8.6 源码详解(7)
dlmalloc 2.8.6 源码详解(7)
本文章由vector03原创, 转载请注明出处.
邮箱地址: mmzsmm@163.com, 欢迎来信讨论.
4. 释放与实现
释放过程相对分配就简单多了, 基本着重在chunk合并, top裁剪, segment释放上. dlmalloc中合并是减少外部碎片最有效的方法了.
4.1 dlfree
释放的主要过程就是根据用户传入的payload,找到chunk指针,然后分别检查前一个和后一个chunk是否可以合并.这里唯一需要注意的就是与dv和top这些特殊chunk的交互.
基本流程如下,
1. 通过用户传入的mem指针计算出chunk指针p.如果FOOTERS打开,则通过magic计算出其所属的mspace指针,并进行校验.
2. 若p是通过direct mmap生成的,则还原其头尾的fake chunk后直接munmap释放并结束.详细内容请参考3.4.2小节的说明.
3. 若p的prev chunk也是free chunk则将p和prev合并.若prev同时又是dv,则还需要考虑p的next chunk.假如next是inused chunk,则直接将合并后的p替换为新的dv并返回,否则进入下一步.
4. 若p的next chunk也是空闲的,则又分为三种情况,
a. next是普通的free chunk,与p进行合并.如果p同时是dv,则更新dv.
b. next同时是top,则与p合并后更新top为p.如果p同时又是dv,则取消当前记录的dv(相当于dv被top吞并了).若top已经超出trim阈值,则执行sys_trim.
c. next同时是dv,则与p合并后更新dv为p.
5. 若p是经历前面步骤的普通chunk,则将更新后的p重新插入分箱系统.如果realse_check满足,则检查并回收当前mspace下所有的free segment.
代码注释如下,
4.2 sys_trim
当dlmalloc在执行free请求时,会检测当前top剩余空间是否超出trim_check规定的阈值.如果是就会尝试收缩当前的top空间.默认情况下, dlmalloc会保留一个粒度(granularity)大小的空间,剩余的都将归还给系统, 可以传入参数pad指定额外的剩余空间(多数情况下是0).另外, 由于top所在区段有可能位于heap区或mmap区,因此也会有不同的收缩方式. 对于heap区的top空间,采取反向MORECORE的方式,而对于mmap区的,则先尝试用mremap进行收缩,如果失败则使用mumap释放掉.假设遇到trim失败的情况, dlmalloc就会自动关闭auto-trimming功能.
源码注释如下,
4.3 release_unused_segments
尽管有auto-trimming压缩top空间,但多数情况下, 只依靠这种方法是无法满足内存释放需求的.尤其是当外部碎片导致top不连续的情况下, auto-trimming可能相当一段时间无法触发.此时, dlmalloc就转而寻找内部可回收的空闲段.由于查找空闲段是一个耗时操作, 且出现的频率较低,所以实际上按照一个周期来进行此操作. 当周期计数为0时,就调用release_unused_segments.
判断一个区段是否空闲也比较简单,因为空闲chunk合并的原因,若当前段的第一个chunk为空闲,且其大小覆盖整个区段除隐藏区域的全部范围, 就可以判定该区段为空闲段.接下来只要unlink空闲chunk,且munmap该区段即可.源码注释如下,
dlmalloc 2.8.6 源码详解(7)