出处

分配:

1)获取分配区的锁,为了防止多个线程同时访问同一个分配区,在进行分配之前需要取得分配区域的锁。线程先查看线程私有实例中是否已经存在一个分配区,如果存在尝试对该分配区加锁,如果加锁成功,使用该分配区分配内存,否则,该线程搜索分配区循环链表试图获得一个空闲(没有加锁)的分配区。如果所有的分配区都已经加锁,那么ptmalloc会开辟一个新的分配区,把该分配区加入到全局分配区循环链表和线程的私有实例中并加锁,然后使用该分配区进行分配操作。开辟出来的新分配区一定为非主分配区,因为主分配区是从父进程那里继承来的。开辟非主分配区时会调用mmap()创建一个sub-heap,并设置好top chunk。

2)将用户的请求大小转换为实际需要分配的chunk空间大小。

3)判断所需分配chunk的大小是否满足chunk_size <= max_fast (max_fast 默认为64B),如果是的话,则转下一步,否则跳到第5步。

4)首先尝试在fastbins中取一个所需大小的chunk分配给用户。如果可以找到,则分配结束。否则转到下一步。

5)判断所需大小是否处在smallbins中,即判断chunk_size <512B是否成立。如果chunk大小处在smallbins中,则转下一步,否则转到第6步。

6)根据所需分配的chunk的大小,找到具体所在的某个small bin,从该bin的尾部摘取一个恰好满足大小的chunk。若成功,则分配结束,否则,转到下一步。

7)到了这一步,说明需要分配的是一块大的内存,或者small bins中找不到合适的chunk。于是,ptmalloc首先会遍历fastbins中的chunk,将相邻的chunk进行合并,并链接到unsorted bin中,然后遍历unsorted bin中的chunk,如果unsorted bin只有一个chunk,并且这个chunk在上次分配时被使用过,并且所需分配的chunk大小属于small bins,并且chunk的大小大于等于需要分配的大小,这种情况下就直接将该chunk进行切割,分配结束,否则将根据chunk的空间大小将其放入small bins或是largebins中,遍历完成后,转入下一步。

8)到了这一步,说明需要分配的是一块大的内存,或者small bins和unsorted  bin中都找不到合适的chunk,并且fastbins和unsorted bin中所有的chunk都清除干净了。从large bins中按照“smallest-first,best-fit”原则,找一个合适的chunk,从中划分一块所需大小的chunk,并将剩下的部分链接回到bins中。若操作成功,则分配结束,否则转到下一步。

9)如果搜索fastbins和bins都没有找到合适的chunk,那么就需要操作top  chunk来进行分配了。判断top  chunk大小是否满足所需chunk的大小,如果是,则从top chunk中分出一块来。否则转到下一步。

10)到了这一步,说明top chunk也不能满足分配要求,所以,于是就有了两个选择: 如果是主分配区,调用sbrk(),增加top chunk大小;如果是非主分配区,调用mmap来分配一个新的sub-heap,增加top chunk大小;或者使用mmap()来直接分配。在这里,需要依靠chunk的大小来决定到底使用哪种方法。判断所需分配的chunk大小是否大于等于mmap分配阈值,如果是的话,则转下一步,调用mmap分配,否则跳到第12步,增加top chunk 的大小。

11)使用mmap系统调用为程序的内存空间映射一块chunk_size align 4kB大小的空间。然后将内存指针返回给用户。

12)判断是否为第一次调用malloc,若是主分配区,则需要进行一次初始化工作,分配一块大小为(chunk_size  +  128KB)  align  4KB大小的空间作为初始的heap。若已经初始化过了,主分配区则调用sbrk()增加heap空间,分主分配区则在top chunk中切割出一个chunk,使之满足分配需求,并将内存指针返回给用户

释放:

1)free()函数同样首先需要获取分配区的锁,来保证线程安全。

2)判断传入的指针是否为0,如果为0,则什么都不做,直接return。否则转下一步。

3)判断所需释放的chunk是否为mmaped  chunk,如果是,则调用munmap()释放mmaped  chunk,解除内存空间映射,该该空间不再有效。如果开启了mmap分配阈值的动态调整机制,并且当前回收的chunk大小大于mmap分配阈值,将mmap分配阈值设置为该chunk的大小,将mmap收缩阈值设定为mmap分配阈值的2倍,释放完成,否则跳到下一步。

4)判断chunk的大小和所处的位置,若chunk_size <= max_fast,并且chunk并不位于heap的顶部,也就是说并不与top  chunk相邻,则转到下一步,否则跳到第6步。(因为与topchunk相邻的小chunk也和top  chunk进行合并,所以这里不仅需要判断大小,还需要判断相邻情况)

5)将chunk放到fastbins中,chunk放入到fastbins中时,并不修改该chunk使用状态位P。也不与相邻的chunk进行合并。只是放进去,如此而已。这一步做完之后释放便结束了,程序从free()函数中返回。

6)判断前一个chunk是否处在使用中,如果前一个块也是空闲块,则合并。并转下一步。

7)判断当前释放chunk的下一个块是否为top  chunk,如果是,则转第9步,否则转下一步。

8)判断下一个chunk是否处在使用中,如果下一个chunk也是空闲的,则合并,并将合并后的chunk放到unsorted  bin中。注意,这里在合并的过程中,要更新chunk的大小,以反映合并后的chunk的大小。并转到第10步。

9)如果执行到这一步,说明释放了一个与top chunk相邻的chunk。则无论它有多大,都将它与top chunk合并,并更新top chunk的大小等信息。转下一步。

10)判断合并后的chunk 的大小是否大于FASTBIN_CONSOLIDATION_THRESHOLD(默认64KB),如果是的话,则会触发进行fastbins的合并操作,fastbins中的chunk将被遍历,并与相邻的空闲chunk进行合并,合并后的chunk会被放到unsorted bin中。fastbins将变为空,操作完成之后转下一步。

11)判断top chunk的大小是否大于mmap收缩阈值(默认为128KB),如果是的话,对于主分配区,则会试图归还top  chunk中的一部分给操作系统。但是最先分配的128KB空间是不会归还的,ptmalloc 会一直管理这部分内存,用于响应用户的分配请求;如果为非主分配区,会进行sub-heap收缩,将top chunk的一部分返回给操作系统,如果top chunk为整个sub-heap,会把整个sub-heap还回给操作系统。做完这一步之后,释放结束,从free()函数退出。可以看出,收缩堆的条件是当前free的chunk大小加上前后能合并chunk的大小大于64k,并且要top  chunk的大小要达到mmap收缩阈值,才有可能收缩堆。

ptmalloc内存分配释放的更多相关文章

  1. delphi 精要-读书笔记(内存分配释放)

    delphi 精要-读书笔记(内存分配释放)     1.内存分为三个区域:全局变量区,栈区,堆区 全局变量区:专门存放全局变量 栈区:分配在栈上的变量可被栈管理器自动释放 堆区:堆上的变量内存必须人 ...

  2. delphi.memory.分配及释放---New/Dispose, GetMem/FreeMem及其它函数的区别与相同,内存分配函数

    来自:http://www.cnblogs.com/qiusl/p/4028437.html?utm_source=tuicool&utm_medium=referral ---------- ...

  3. c++内存分配

    [导语] 内存管理是C++最令人切齿痛恨的问题,也是C++最有争议的问题,C++高手从中获得了更好的性能,更大的自由,C++菜鸟的收获则是一遍一遍的检查代码和对C++的痛恨,但内存管理在C++中无处不 ...

  4. openssl内存分配,查看内存泄露

    openssl内存分配 用户在使用内存时,容易犯的错误就是内存泄露.当用户调用内存分配和释放函数时,查找内存泄露比较麻烦.openssl提供了内置的内存分配/释放函数.如果用户完全调用openssl的 ...

  5. ptmalloc,tcmalloc和jemalloc内存分配策略研究 ? I'm OWen..

    转摘于http://www.360doc.com/content/13/0915/09/8363527_314549949.shtml 最近看了glibc的ptmaoolc,Goolge的tcmall ...

  6. C语言中的内存分配与释放

    C语言中的内存分配与释放 对C语言一直都是抱着学习的态度,很多都不懂,今天突然被问道C语言的内存分配问题,说了一些自己知道的,但感觉回答的并不完善,所以才有这篇笔记,总结一下C语言中内存分配的主要内容 ...

  7. DLL函数中内存分配及释放的问题

    DLL函数中内存分配及释放的问题 最近一直在写DLL,遇到了一些比较难缠的问题,不过目前基本都解决了.主要是一些内存分配引起问题,既有大家经常遇到的现象也有特殊的 情况,这里总结一下,做为资料. 错误 ...

  8. 内存管理概述、内存分配与释放、地址映射机制(mm_struct, vm_area_struct)、malloc/free 的实现

    http://blog.csdn.net/pi9nc/article/details/23334659 注:本分类下文章大多整理自<深入分析linux内核源代码>一书,另有参考其他一些资料 ...

  9. 动态内存分配(new)和释放(delete)

    在之前我们所写过的程序中,所必需的内存空间的大小都是在程序执行之前就已经确定了.但如果我们需要内存大小为一个变量,其数值只有在程序运行时 (runtime)才能确定,例如有些情况下我们需要根据用户输入 ...

随机推荐

  1. 【刷题】【LeetCode】总

    参考资料 用动画的形式呈现解LeetCode题目的思路 目录: 000-十大经典排序算法 001-两数之和-easy 暴力法(遍历):两遍哈希表:一遍哈希表 002- 003- 004- 005- 0 ...

  2. To B Vs To C

    谈谈 To B 业务的难点https://tangjie.me/blog/259.html

  3. JavaScript速记

    JavaScript常见知识点积累,包括数据类型.数值转换.对象.原型与原型链.作用域与闭包等等,持续整理更新,如有错误请指正,甚是感激 本文链接:JavaScript那些磨人的小妖精 作者:狐狸家的 ...

  4. Number和toString中的坑

    在之前的一篇文章 JavaScript中的大数相加 中,在做大数相加时, 突然想到 数字.toString方法 会报错,但是作为函数参数传进来,直接调用 toString 方法却不会报错 上网搜了看看 ...

  5. 你值得拥有的Mac PS滤镜插件和特效处理软件合集,不要错过!

    以下几款是Mac上强大的Photoshop滤镜插件和特效,可以让我们更加高效率的使用PS,设计和处理出精美的图片. 1. Alien Skin Eye Candy Eye Candy是一款强大酷炫的P ...

  6. getopt()函数 命令解析

    今天做计算机系统结构实验时学习到一个非常方便的命令解析函数getopt(),简单做个笔记,方便日后复习. 头文件:#include<unistd.h> 函数原型:int getopt(in ...

  7. Oracle时间函数

    YYYY年 Q季度 MM月 month月 WW当年第几周 W本月第几周 DDD 当年第几天 DD当月第几天 D当周内第几天 DY当周内星期几 day当周内星期几 HH或HH12:12进制小时数 HH2 ...

  8. react native( rn) 中关于navigationOptions中headerRight 获取navigation的问题 rn

    使用以下代码获取navigation static navigationOptions = ({ navigation, navigationOptions }) => { const { pa ...

  9. redis---------AOF文件异常导致的redis无法载入

    AOF损坏时的对策1.若在写AOF文件时Server崩溃则可能导致AOF文件损坏而不能被Redis载入.可通过如下步骤修复: 创建一个AOF文件的备份: cp appendonly.aof appen ...

  10. Linux之防火墙管理篇[Ubuntu:ufw]

    前言 由于近期,腾讯云服务器就要到期了,学生优惠即将失效了,所以准备将数据库和项目迁移到vultr上.然而,在使用nivicat连接mysql数据库的过程中,却屡次出现:Can't connect t ...