如果对ptmalloc的基本设计还不熟悉,请先看:https://blog.csdn.net/songchuwang1868/article/details/89951543

一、bin数组

ptmalloc的实现细节

bin数组大体分成三个部分:

1、unsored bin数组

  • 暂存一些没有排序的数据
  • unsored bin数组中的块马上就会分配给用户或者放到small/large bin数组中

2、small bin数组

  • 每项指向一个双向链表,链表中每一项都是一样的大小
  • 最小32Byte,16Byte递增,直到1K

3、large bin数组

  • 每项是一个范围
  • 每项指向的是双向链表,双向链表维护有序的块,除了fd和bk外还有fd_nextsize和bk_nextsize的使用

二、fast bin数组

ptmalloc的实现细节

  • 独立于前面的bin数组
  • 最小32Byte,16Byte递增,直到128Byte
  • 单向链表,便于使用CAS实现无锁操作
  • 使用arena分配内存时,先到fast bin中找,找到匹配的块直接返回,找到更大的块,切割需要的大小返回。由于fast bin中的块很散碎而没有找到,摘取fast bin中所有的块,进行合并。将合并后更大的块放到unsored bin中,遍历unsored bin找需要的块,遍历过程中顺便将unsored bin中的块放到small bin和large bin中。

三、arena

ptmalloc的实现细节

  • 每个arena中包含了一个bin和一个fast_bin
  • 每个进程中有最多有N个arena,N=cpu_num*2(32位系统),也就是说arena数仅仅与cpu数目相关
  • ptmalloc是C库中的功能,所以必定在用户层上,所以必定每个进程一份,也就是说每个进程有N个arena。所有跨越进程的共享资源都在内核中维护
  • 同一个进程中的多个线程共享这对应进程中的N个arena
  • 多个线程可以绑定到同一个arena上,当部分arena耗尽的情况下,一个线程也可能切换到其他arena

四、top chunk

ptmalloc的实现细节

  • 每当arena管理的内存不够时,使用mmap(非主arena)或者brk(主arena)分配1M大小的堆空间
  • 虽然分配了1M的空间,但不是直接使用,而是每次用4K,也就是每次用一个页面。未用到的页面设定为protected页,如果用户误写了protected页,段错误
  • 在一个可用页中切割chunk
  • top chunk指向已切割chunk的最后,换言之,每次切割新的chunk,从top chunk处开始
  • 当归还内存时,归还的chunk会与top chunk合并(也就是top chunk上移)

五、heap

ptmalloc的实现细节

  • 这里的heap不是内存布局中的heap,而是一个malloc中的结构体
  • arena可能使用的内存超过1M,会分配多个Heap,并用链表维护
  • top chunk位域最后一个heap的最后一个chunk的后面
  • arena位于第一个Heap中
  • Heap1 M对齐,任意一个chunk要找到自己属于哪一个arena是很容易的,只看自己的高位,便能找到自己所属的heap,再定位到相应的arena
  • 归还内存,使top chunk位移到heap开始的地方,说明整个heap都归还了,ptmalloc将整个heap还给系统
  • ptmalloc这里存在一个槽点,如果中间的heap基本空闲(但有几个chunk还没有回收),但对应的heap却得不到回收

六、thread cache

最新版的ptmalloc向tc malloc学习,使用了线程局部存储来优化设计,线性局部存储不熟请看:https://blog.csdn.net/songchuwang1868/article/details/90143332

ptmalloc中的thread cache有如下特点:

  • tcache与small bin类似,最小32Byte,16Byte递增,直到1K
  • 每个链表最多7个chunk
  • 每次申请内存,先到thread cache中找,没有再到arena中取找

七、分配流程

  1. 有thread cache,先到thread cache中找
  2. 到fast bin中找
  3. 到small bin中找,找到返回,没有找到开始清理fast bin
  4. 将fast bin中的块取下来,相邻的合并,放到unsorted bin中
  5. 遍历unsorted bin,如果能够分配,进行分配,不能分配将其挂到bin中相应的位置
  6. 到large bin中找,如果能够分配,进行切割,一部分交给用户,剩余部分放到unsorted bin中
  7. 如果遍历完lare bin没有找到,mmap新内存

八、回收流程

  1. 有thread cache,且大小合适,放到thread cache中
  2. 放到fast bin中,无论当前fast bin中有多少块,只要在fast bin的chunk size范围内,就放到fast bin中
  3. 放到bin(包括small bin和large bin)中,放的时候看能不能与相邻块合并,合并后放到unsorted bin中

相关文章:

  • 2018-10-03
  • 2021-10-04
  • 2020-06-17
  • 2020-11-05
  • 2019-12-02
  • 2021-11-07
  • 2021-11-20
  • 2021-11-01
猜你喜欢
  • 2021-09-13
  • 2021-09-07
  • 2019-01-25
  • 2021-11-07
  • 2021-05-09
  • 2021-11-05
  • 2020-07-18
  • 2021-11-30
相关资源
相似解决方案