首页 > 代码库 > 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是否可以合并.这里唯一需要注意的就是与dvtop这些特殊chunk的交互.

基本流程如下,

1. 通过用户传入的mem指针计算出chunk指针p.如果FOOTERS打开,则通过magic计算出其所属的mspace指针,并进行校验.

2. p是通过direct mmap生成的,则还原其头尾的fake chunk后直接munmap释放并结束.详细内容请参考3.4.2小节的说明.

3. pprev chunk也是free chunk则将pprev合并.prev同时又是dv,则还需要考虑pnext chunk.假如nextinused chunk,则直接将合并后的p替换为新的dv并返回,否则进入下一步.

4. pnext chunk也是空闲的,则又分为三种情况,

                   a.      next是普通的free chunk,p进行合并.如果p同时是dv,则更新dv.

                   b.      next同时是top,则与p合并后更新topp.如果p同时又是dv,则取消当前记录的dv(相当于dvtop吞并了).top已经超出trim阈值,则执行sys_trim.

                   c.      next同时是dv,则与p合并后更新dvp.

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)