bins

admin 2022年5月16日02:48:05评论98 views字数 2894阅读9分38秒阅读模式
bins
这一章主要讲述一下各个bins的内容


1

单链表:fastbintcache

2

双链表:unsortedbin、smallbin、largebin
01
fastbin结构
fast bins:fast bins是bins的高速缓冲区,大约有10个定长队列。当用户释放一块不大于max_fast(默认值64)的chunk(一般小内存)的时候,会默认会被放到fast bins上。当用户下次需要申请内存的时候首先会到fast bins上寻找是否有合适的chunk,然后才会到bins上空闲链表里面查找的chunk。ptmalloc会遍历fast bin,看是否有合适的chunk需要合并到bins上。主要放置在fastbinsY数组上。fastbin非常像高速缓存 cache,主要用于提高小内存分配效率。相邻空闲 chunk 不会被合并,这会导致外部碎片增多但是free效率提升。注意 fast bins 是 10 个 LIFO 的单链表。最后三个链表保留未使用。chunk大小(含chunk头部):0x10-0x40(64位0x20-0x80),相邻bin存放的大小相差0x8(0x10)。
bins

02
tcache结构
tcache是libc2.26之后引进的一种新机制,类似于fastbin一样的东西,每条链上最多可以有 7 个 chunk,free的时候当tcache满了才放入fastbin,unsorted bin,malloc的时候优先去tcache找。
bins

03
双链表bins
  • unsorted bin:是bins的一个缓冲区,bins数组下标为1的即是unstored bin。当用户释放的内存大于max_fast或者fast bins合并后的chunk都会进入unsorted bin上。当用户malloc的时候,先会到unsorted bin上查找是否有合适的bin,如果没有合适的bin,ptmalloc会将unsorted bin上的chunk放入bins上,然后到bins上查找合适的空闲chunk。
  • small bins:小于512字节(64位机器1024字节)的chunk被称为small chunk,而保存small chunks的bin被称为small bin。数组从2开始编号到63,前62个bin为small bins,small bin每个bin之间相差8个字节(64位16字节),同一个small bin中的chunk具有相同大小。起始bin大小为16字节(64位系统32)。
  • large bins:大于等于512字节(64位机器1024字节)的chunk被称为large chunk,而保存large chunks的bin被称为large bin。位于small bins后面,数组编号从64开始,后64个bin为large bins。同一个bin上的chunk,可以大小不一定相同。large bins都是通过等差步长的方式进行拆分。(以32位系统为例,前32个bin步长64,后16个bin步长512,后8个步长4096,后四个32768,后2个262144)(编号63到64的步长)。起始bin大小为512字节(64位系统1024)。
bins

bins

bins

bins

unsorted bin:

每次取最后的一个unsorted chunk。

  1. 如果unsorted chunk满足以下四个条件,它就会被切割为一块满足申请大小的chunk和另一块剩下的chunk,前者返回给程序,后者重新回到unsorted bin。

  • 申请大小属于small bin范围

  • unosrted bin中只有该chunk

  • 这个chunk同样也是last remainder chunk

  • 切割之后的大小依然可以作为一个chunk

  • 否则,从unsorted bin中删除unsorted chunk。

    • 若unsorted chunk恰好和申请大小相同,则直接返回这个chunk

    • 若unsorted chunk属于small bin范围,插入到相应small bin

    • 若unsorted chunk属于large bin范围,则跳转到3。

  • 此时unsorted chunk属于large bin范围。

    • 若对应large bin为空,直接插入unsorted chunk,其fd_nextsize与bk_nextsize指向自身。

    • 否则,跳转到4。

  • 到这一步,我们需按大小降序插入对应largebin。

    • 若对应large bin最后一个chunk大于unsorted chunk,则插入到最后

    • 否则,从对应large bin第一个chunk开始,沿fd_nextsize(即变小)方向遍历,直到找到一个chunk fwd,其大小小于等于unsorted chunk的大小

    • 若fwd大小等于unsorted chunk大小,则插入到fwd后面

    • 否则,插入到fwd前面直到找到满足要求的unsorted chunk,或无法找到,去top chunk切割为止。

    small bins

    小于 0x200(0x400)B 的 chunk 叫做 small chunk,而 small bins 可以存放的就是这些 small chunks。chunk 大小同样是从 16B 开始每次+8B。

    small bins 是 62 个双向循环链表,并且是 FIFO 的,这点和 fast bins 相反。同样相反的是相邻的空闲 chunk 会被合并。

    chunk大小:0x10-0x1f0B(0x20-0x3f0),相邻bin存放的大小相差0x8(0x10)B。

    释放非fast chunk时,按以下步骤执行:

    1. 若前一个相邻chunk空闲,则合并,触发对前一个相邻chunk的unlink操作

    2. 若下一个相邻chunk是top chunk,则合并并结束;否则继续执行3

    3. 若下一个相邻chunk空闲,则合并,触发对下一个相邻chunk的unlink操作;否则,设置下一个相邻chunk的PREV_INUSE为0

    4. 将现在的chunk插入unsorted bin。

    5. 若size超过了FASTBIN_CONSOLIDATION_THRESHOLD,则尽可能地合并fastbin中的chunk,放入unsorted bin。若top chunk大小超过了mp_.trim_threshold,则归还部分内存给OS。

    large bins

    大于等于 0x200(0x400)B 的 chunk 叫做 large chunk,而 large bins 可以存放的就是这些 large chunks。

    large bins 是 63 个双向循环链表,插入和删除可以发生在任意位置,相邻空闲 chunk 也会被合并。chunk 大小就比较复杂了:

    • 前 32 个bins:从 0x200B 开始每次+0x40B

    • 接下来的 16个bins:每次+0x200B

    • 接下来的 8 个bins:每次+0x1000B

    • 接下来的 4 个bins:每次+0x8000B

    • 接下来的 2 个bins:每次+0x40000B

    • 最后的 1 个bin:只有一个 chunk,大小和 large bins 剩余的大小相同

    注意同一个 bin 中的 chunks 不是相同大小的,按大小降序排列。这和上面的几种 bins 都不一样。而在取出chunk时,也遵循best fit原则,取出满足大小的最小chunk。

    原文始发于微信公众号(由由学习吧):bins

    • 左青龙
    • 微信扫一扫
    • weinxin
    • 右白虎
    • 微信扫一扫
    • weinxin
    admin
    • 本文由 发表于 2022年5月16日02:48:05
    • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                     binshttps://cn-sec.com/archives/1009389.html

    发表评论

    匿名网友 填写信息