精华内容
下载资源
问答
  • ptmalloc

    2018-06-10 16:01:49
    ptmalloc折中上述目标: 具有长生命周期的大内存分配使用mmap。 特别大的内存分配总是使用mmap。 具有短生命周期的内存分配使用brk。 尽量只缓存临时使用的空闲小内存块,对大内存块或是长生命周期的大内存...

    内存管理器的设计目标:

    1.最大兼容性
    2.最大可移植性
    3.浪费最小空间
    4.最快的速度
    5.最大可调式性

    ptmalloc折中上述目标:

    1. 具有长生命周期的大内存分配使用mmap。
    2. 特别大的内存分配总是使用mmap。
    3. 具有短生命周期的内存分配使用brk。
    4. 尽量只缓存临时使用的空闲小内存块,对大内存块或是长生命周期的大内存块在释放时都直接归还给操作系统。
    5. 对空闲的小内存块只会在malloc和free的时候进行合并,free时空闲内存块可能放入pool中,不一定归还给操作系统。
    6. 收缩堆的条件是当前free的块大小加上前后能合并chunk的大小大于64KB、,并且堆顶的大小达到阈值,才有可能收缩堆,把堆最顶端的空闲内存返回给操作系统。
    7. 需要保持长期存储的程序不适合用ptmalloc来管理内存。
    8. 不停的内存分配ptmalloc会对内存进行切割和合并,会导致一定的内存碎片

    brk()和mmap()

    brk():
    --
     .bss 段之上的这块分配给用户程序的空间被称为 heap (堆). start_brk 指向 heap 的开始, 而 brk 指向 heap 的顶部. 可以使用系统调用 brk 和 sbrk 来增加标识 heap 顶部的 brk 值, 从而线性的增加分配给用户的 heap 空间. 在使用malloc之前, brk 的值等于start_brk, 也就是说 heap 大小为0. ptmalloc 在开始时, 若请求的空间小于 DEFAULT_MMAP_THRESHOLD (128K bytes)时, ptmalloc 会调用sbrk增加一块大小为 ( 128 KB + chunk_size ) align 4K 的空间作为heap. 这就是前面所说的 ptmalloc 所维护的分配空间, 当用户请求内存分配时, 首先会在这个区域内找一块合适的 chunk 给用户. 当用户释放了 heap 中的 chunk 时, ptmalloc 又会使用 fastbins 和 bins 来组织空闲 chunk.  若需要分配的 chunk 大小小于 DEFAULT_MMAP_THRESHOLD, 而 heap 空间又不够, 则此时 ptmalloc 会通过 sbrk 调用来增加 heap 值, 也就是增加 “top chunk”的大小, 每次 heap 增加的值都会 align 到4k bytes.
    
    mmap():
    --
    用户的请求超过 DEFAULT_MMAP_THRESHOLD , 并且使用 sbrk 分配失败的时候, ptmalloc 会尝试使用 mmap 直接映射一块内存到进程内存空间(我机器上是在0x40159000地址处). 使用 mmap 直接映射的 chunk 在释放时直接解除映射, 而不再属于进程的内存空间. 任何对该内存的访问都会产生段错误. 而在 heap 中分配的空间则可能会留在进程内存空间内.

    ptmalloc()

    为了支持多线程:
    --
    增加了非主分配区支持,主分配区和非主分配区形成一个环形链表进行管理,每一个分配区使用互斥锁使多线程对于该分配区的访问互斥。如果只有主分配区,每次分配内存都必须对主分配区​加锁,分配完成后再释放锁。在多线程的环境下,对主分配区的锁的竞争很激烈,严重影响了malloc的分配效率。
    
    主分配区和非主分配的区别:
    --
    1>每个进程只有一个主分配区,可以有多个非主分配区,ptmalloc根据系统对分配区的争用情况动态的增加非主分配区的个数,分配区的数量一旦增加了就不会再减少。
    2>主分配区可以使用brk() 和 mmap()向系统申请虚拟内存,而非主分配区只能使用mmap()申请一个HEAP_MAX_SIZE(32下是1M),用户申请时候再进行分割
    3>主分配区可以访问heap区域,如果用户不调用brk(),分配程序就可以保证分配到连续的虚拟内存,因为一个进程只有一个主分配区使用sbrk()分配heap区域的虚拟内存。如果主分配区的内存时通过mmap()向系统申请的,当free该内存时,主分配区会直接调用munmap()将内存归还给操作系统。

    chunk:
    这里写图片描述

    使用中的chunk:
    --
    <1> chunk指针指向chunk开始的地址;mem指针指向用户内存块开始的地址
    <2> p=0时,表示前一个chunk为空闲,prev_size才有效​
    <3> p=1时,表示前一个chunk正在使用,prev_size无效。 p主要用于内存块的合并
    <4> ptmalloc分配的第一个块总是将p设为1,以防止程序引用到不存在的区域。
    <5> M=1 为mmap映射区域分配;M=0为heap区域分配
    <6> A=1 为非主分区分配;A=0 为主分区分配
    
    空闲chunk:
    --
    <1> 空闲的chunk会被放置到空闲的链表bins上。当用户申请内存malloc的时候,会先去查找空闲链表bins上是否有合适的内存。
    <2> fp和bp分别指向前一个和后一个空闲链表上的chunk
    <3> fp_nextsize和bp_nextsize分别指向前一个空闲chunk和后一个空闲chunk的大小,主要用于在空闲链表上快速查找合适大小的chunk。
    <4> fp、bp、fp_nextsize、bp_nextsize的值都会存在原本的用户区,这样就不需要专门为每个chunk准备单独的内存存储指针了。

    chunk中的空间复用:

    fp、bp、fp_nextsize、bp_nextsize的值都会存在原本的用户区
    这些指针一共占用4*4=16B,但是这些只是用于维护空闲链表的,当使用中就无意义,且浪费,所以放在用户空间,空闲时加入。

    chunk管理:
    这里写图片描述

    将大小相似的chunk用双链表维护,一个链称为一个bin.
    分类:
    
    fast bins: 这是一个数组,用于记录所有的fast bins:
    bins: 这也是一个数组用于记录除fast bins之外的所有bins
    一共有128个bins,分别是:
    bin 1 为 unsorted bin
    bin 2 到 64为small bin
    bin 65到 128为large bin
    
    fast bins:
    --
    维护7条单链表<16B.24B.32B.40B.48B.56B.64B>
    是small bins的高速缓冲区,由单链表维护,程序中释放的小内存(<=64B)会被放至此处,分配小内存时会优先在fsat bins中找,找不到才会去bins中找,特定时刻会进行合并放至unshort bin
    
    unshort bins:bins的一个缓冲区,为了加快分配的速度
    --
    被用户释放的chunk大于max_fast,或者fast bins中的空闲chunk合并后,这些chunk首先会被放到unsorted bin队列中,在进行malloc操作的时候,如果在fast bins中没有找到合适的chunk,则ptmalloc会先在unsorted bin中查找合适的空闲chunk,然后才查找bins。如果unsorted bin不能满足分配要求。malloc便会将unsorted bin中的chunk加入bins中。然后再从bins中继续进行查找和分配过程。
    
    small bins:
    --
    同一个small bin中的chunk具有相同的大小。两个相邻的small bin中的chunk大小相差8bytes,small bins中的chunk按照最近使用顺序进行排列,最后释放的chunk被链接到链表的头部,而申请chunk是从链表尾部开始,这样,每一个chunk 都有相同的机会被ptmalloc选中.
    
    large bins: >=512B
    --
    63个large bin,每个bin中的chunk大小不是一个固定的等差数列,而是分成6组bin,每组bin是一个固定的等差数列。每组bin数量依次为32、16、8、4、2、1,公差依次为64B、512B、4096B、32768B、262144B等。
    
    top chunk:
    --
    Fast bin、Unsorted bin、Small bin和 Large bin中保存的都是用户曾经释放的内存块(可能经过合并);
    top chunk包含Arena扩容的部分,不属于任何bin!
    
    .non_main非主分配区:
    对于非主分配区会预先从 mmap 区域分配一块较大的空闲内存模拟 sub-heap,通过管理sub-heap 来响应用户的需求,因为内存是按地址从低向高进行分配的,在空闲内存的最高处,必然存在着一块空闲chunk,叫做 top chunk。当bins和fast bin都满足不了用户的需求,ptmalloc会从top chunk分出一块内存给用户,如果top chunk空间不足,会重新分配一个sub-heap,将top chunk迁移到行的sub-heap上。新的sub-heap和旧的sub。在分配过程中,top chunk的大小随着切割动态变化。
    
    .main主分配区:
    主分配区是唯一能够映射进程 heap 区域的分配区,它可以通过 sbrk()来增大或是收缩进程 heap 的大小。top chunk在heap的最上面,如果申请内存时,top chunk空间不足,ptmalloc会调用 sbrk()将的进程 heap 的边界 brk 上移,然后修改 top chunk 的大小。

    内存分配过程:

    这里写图片描述

    缺陷:

    1> 后分配的内存先释放,因为 ptmalloc 收缩内存是从 top chunk 开始,如果与 top chunk 相邻的 chunk 不能释放, top chunk 以下的 chunk 都无法释放。
    2> 多线程锁开销大, 需要避免多线程频繁分配释放==> #内存暴增
    3> 内存从threadareana中分配, 内存不能从一个arena移动到另一个arena, 就是说如果多线程使用内存不均衡,容易导致内存的浪费。 比如说线程1使用了300M内存,完成任务后glibc没有释放给操作系统,线程2开始创建了一个新的arena, 但是线程1300M却不能用了。
    4> 每个chunk至少8字节的开销很大
    5> 不定期分配长生命周期的内存容易造成内存碎片,不利于回收。 64位系统最好分配32M以上内存,这是使用mmap的阈值。

    “`

    展开全文
  • ptmalloc2-开源

    2021-08-06 18:36:44
    已知最快和最好的动态内存分配器之一,直接从 GNU glibc v2.3.3 派生而来,但修补了 Windows 支持。注意:nedmalloc 取代了 ptmalloc2,并且该项目将不再维护!
  • Ptmalloc总结

    2018-01-31 02:10:13
    有关于ptmalloc的一些总结 在glibc下的ptmalloc的一点点分析。 关于chunk组织 chunk指针指向一个chunk的开始处,而mem指针才是真正分配给用户的储存空间。 chunk的第二个域的最低一位P表示前一个chunk是否是在使用...

    有关于ptmalloc的一些总结

    在glibc下的ptmalloc的一点点分析。

    关于chunk组织

    图片描述

    • chunk指针指向一个chunk的开始处,而mem指针才是真正分配给用户的储存空间。
    • chunk的第二个域的最低一位P表示前一个chunk是否是在使用当中(0代表前一个空闲,1代表在使用当中)。
      当P为0时,此时prev_size才有效,第一个域表示的是前一个chunk的size,可以通过这个值取到前一个chunk的开始地址;当P为1时,表示前一个chunk在使用当中,prev_size无效。
      ptmalloc分配的第一个chunk总是将P设为1,以防止程序引用到不存在的区域。
    • chunk第二个域倒数第二位M(0表示是从mmap映射区域分配的,1表示heap区域分配)
    • chunk第二个域倒数第三位A(1表示主分配区,0非主分配区)
    • 当chunk空闲时,user_data区域储存了4个指针。
      指针fd指向后一个空闲的chunk;
      指针bk指向前一个空闲的chunk;
      fd_nextsize以及bk_nextsize两个指针用于加快在large bin中查找最近匹配的空闲chunk
    • chunk利用标志来管理使用和空闲的内存,减少了内存归还所带来的系统消耗,并且在一个未使用的chunk中,它的prev_size部分是可以被紧挨的上一个使用的chunk空间复用的。

    关于bins

    用户free掉的内存并不是直接就归还给系统,ptmalloc会统一管理heap和mmap映射区域中的空闲chunk,当用户有分配请求时候,ptmalloc会首先在空闲的chunk中挑选一块符合需求的交给用户,这样避免了频繁的系统调用,降低了内存分配的开销。

    • ptmalloc将相似大小的chunk用双向链表链接起来,这样的一个链表就被叫做bin,ptmalloc一共维护了128个bin,并用一个数组来储存这些bin图片描述
    • 数组第一个是unsorted bin,ptmalloc在合并空闲的chunk时会放入,如果用户释放的chunk大于max_fast或者fast bins中空闲的chunk合并之后都会放入unsorted bin中。
      ptmalloc在fast bins中没有找到合适的chunk就会进入unsorted bins中查找,如果还是没有找到,就会把unsorted bin汇总的chunk加入到bins当中,这样看来,unsorted bin类似于bins中的一个缓冲区。
    • 数组的2到64个bin被称为small bins,同一个small bin中的chunk大小相同,两个相邻的small bin相差8字节;
    • 后面64个bin称为large bins,这里面的每一个bin都是一个范围内的chunk并且是按大小序排列好的;
    • fast bins
    • 引入它是因为在分配时可能会经常申请和释放一些很小的空间,分配器合并之后又需要分割,这样太过低效,故而在不大于max_fast(默认值是64B)的chunk释放后会先被放到fast_bins中,不去改变他们的P标志位,所以他们无法合并,在小于等于max_fast时首先在fast_bins中查找相应的空闲块。
    • Top chunk
      这是一开始所划分出来的一个大空闲内存,如果bins之后还没有满足的chunk,那么通过Top chunk来划分一个新的chunk给用户
    • mmaped chunk
      当top chunk都不能满足时,通过mmap将页映射到进程空间中,这样的chunk被free时候直接解除映射归还给系统。
    • last remainder
      当所请求的chunk是一个小空间的,但是在small bins中又没有合适的chunk,那么从last remainder chunk中分裂出两个chunk,一个给用户,一个变成新的last remainder chunk。

    sbrk和mmap

    .bss段之上的分配给用户程序的空间叫做堆,start_brk指向堆的开始,brk指向堆的顶部,可以通过brk()和sbrk()来增加标识堆顶的brk的值。

    在使用malloc之前brk等于start_brk,请求分配时若是请求空间小于mmap的分配阈值(mmap threshold,默认是128k),主分配区会调用sbrk()增加一块大小为4k的空间作为heap。非主分配区则会调用mmap映射一块HEAP_MAX_SIZE(32位系统下默认1M,64位系统下默认是64M)大小的空间作为sub-heap。

    ptmalloc分配概述

    1. 获取分配区的锁,为了防止多个线程同时访问同一个分配区。
    2. 将用户请求的大小转换位实际需要分配的chunk空间的大小。
    3. 判断所需分配的chunk大小是否小于max_fast,如果大于则跳转第五步。
    4. 首先城市在fast bins中查找一个chunk给用户,如果存在则分配结束。
    5. 判断所需大小是否处在small bins中,如果chunk大小处在small bins中,则根据所需chunk大小,找到具体所在的某个索small bin,从bin的尾部摘取一个满足大小的chunk返回给用户。否则到第六步。
    6. 到了这一步说明分配的是一个大块内存或者small bins中没有合适的chunk。那么首先会遍历fast bins中的chunk与相邻chunk合并链接到unsorted bin中,然后遍历unsorted bin中的chunk,如果只有一个上次分配已经使用的chunk,并且这个chunk满足small bins的要求且这个chunk符合用户所要求的大小,那么直接对这个chunk进行分割返回给用户,否则将它放入small bins或者large bins中。
    7. 排除了fast bins和unsorted bin中的chunk,到了这一步从large bins中找到一个合适的chunk,从中划分一块所需大小的chunk,并将剩余部分链接回bins中,若分配成功则结束,否则下一步。
    8. 如果bins中都没有合适的chunk,那么则对top chunk进行分割来分配给用户,成功则结束,否则下一步。
    9. 到了这一步证明top chunk不能满足需求,那么对于主分配区就调用sbrk()来增加top chunk的大小;对于非主分配区则会调用mmap来分配一个新的sub-heap增加top chunk的大小或者直接mmap()直接映射分配。

    关于内存的回收

    1. free()函数也会先获取分配区的锁。
    2. 判空,如果是空直接return。
    3. 判断所需释放的chunk是不是mmaped chunk,若是是,直接调用munmap()释放mmaped chunk,解除内存映射。否则下一步。
    4. 判断chunk的大小和所处的位置,如果chunk_size<=max_fast,并且chunk不在堆顶,也就不与top chunk相邻,则转到下一步,否则转到第六步。
    5. 将chunk放到fast bins中,将chunk放入到fast bins中,并不修改当前的chunk的使用标志P,之后释放结束从free()中返回。
    6. 判断前一个chunk是否在使用当中,如果前一个块也是空闲块那么进行合并。
    7. 判断当前释放的下一个块是不是top chunk,如果是则转到第九步,否则下一步。
    8. 判断下一个chunk是否处在使用中,如果下一个chunk也是空闲的则合并后放入unsorted bin中。
    9. 如果执行到这一步,说明释放了一个和top chunk相邻的chunk。
    10. 判断合并后的chunk大小是否大于FASTBIN_CONSOLDATION_THRESHOLD(默认64KB),如果是则触发进行fast bins的合并操作。
    11. 判断top chunk是否大于mmap的收缩阈值(默认128K),如果是的话,对于主分配区,则会试图归还top chunk中的一部分给操作系统。
    展开全文
  • ptmalloc2

    2018-02-22 18:58:00
    本文参考华庭(庄明强)的ptmalloc2 源码剖析 简介: ptmalloc实现了malloc(),free()以及一组其他函数,以提供动态内存管理,同时支持多线程。分配器处于用户空间和内核空间之间,响应用户的分配请求,向操作...

    本文参考华庭(庄明强)的ptmalloc2 源码剖析

    • 简介:

    ptmalloc实现了malloc(),free()以及一组其他函数,以提供动态内存管理,同时支持多线程。分配器处于用户空间和内核空间之间,响应用户的分配请求,向操作系统申请内存。总体思想是先“批发”一块大内存,而后“零售”给用户,同时也实现了高效的回收机制。

     

    • Main_area / non_main_area(主分配区和非主分配区):

    在linux之前版本使用的内存分配机制只有一个主分配区,然而多线程下访问要加锁,所以在ptmalloc中区分出了主分区和非主分区。主分区只有一个,而非主分区可以有多个,分区一旦增加就不会减少。

    主分区可以访问heap和memory mapping segment(可调用brk()/sbrk()/mmap()),而非主分区只能访问memory mapping segment(只可以调用mmap())。

     

    • chunk组织

    ptmalloc通过chunk来管理内存,给User data前存储了一些信息,使用边界标记区分各个chunk。

    这个是一个使用中的chunk,返回给用户的指针是上图的mem,在mem上方分别存放了前一个chunk的大小和本chunk的大小,chunk对齐(alignment = 2 ^n; n>=3),对于默认8字节对齐后10个bit为一定为0,则可以用后3个bit存储其他信息。

    A:1表示主分配区 0表示非主分配区

    M:表示是否使用mmap()直接从进程mmap映射区域分配, 1表示是, 0表示不是。(ptmalloc认为长生命周期的大内存使用mmap,回收一个由mmap直接映射的内存时会更改mmap分配和收缩阈值,因为如果频繁使用mmap()分配内存,每次mmap映射物理页需要将物理页清零,浪费系统资源)。

    p:1表示前一个chunk正在使用,0表示前一个chunk为空闲。

     

    • chunk的空间复用和边界标记法

    对于空闲的chunk增加了额外的指针

     

    红色框住的只有在较大的chunk中才存在。

    为了使chunk所占空间最小,使用了空间复用

    由于对于ptmalloc来说每次都是向操作系统申请一大块内存,然后分割成不同的chunk,所以对于查找上一个chunk直接可以用chunk指针减去前一个的大小,查找下一个也是同样的道理,只用计算指针就方便的多。同时在后面的合并中也只用改结构体中相应的值即可。

    p位标识了前一个chunk是否空闲,如果p为1时(前一块正在使用),Sizeof previous chunk就没有意义,而这块空间就可以被上一块有数据的chunk使用。下图简单地表示了chunk的空间复用

     

     

    所以对于此处的next chunk中的prev域虽然是属于他的,但里面内容却存放的是上一个chunk的User data,而上一个chunk的size 应该为    (data + 8 - 4)align to 8B,这个就是实际分配的内存大小。

    边界标记法:简单来说类似于循环首次适应算法,因为空闲的chunk组成了一个双向循环链表,确保了内存分配不会因为首次适应积攒在头部。

     

    • 内存分配过程:(分配回收过程文档中有详细说明)

     

    • 内存回收过程

     

     

    • 配置选项
    1. M_MXFAST:设置fast bin中最大大小。多使用fast bin效率很高但设置的过大会导致内存随便过多,频繁清理合并fast bin会因加锁而影响效率。
    2. M_TRIM_THRESHOLD:设置mmap收缩阈值,-1关闭收缩
    3. M_MMAP_THRESHOLD:设置mmap分配阈值,默认128k
    4. M_MMAP_MAX:设置使用mmap分配内存的最大块数,默认64k

     

    • 避免Glibc内存暴增
    1. 后分配的先释放,因为ptmalloc收缩内存只能够从top chunk开始,所以当离top chunk最近的那一块内存没有释放时,ptmalloc是不会释放收缩的。
    2. 防止内存泄漏,如果泄露的刚好是top chunk最近的内存,则无法收缩
    3. 不合适管理长生命周期的内存
    4. 可以通过优化配置按照实际情况优化
    5. 多线程不适合 对于非主分区一旦增加不会减少,所以在对锁竞争激烈时,会快速的增加非主分配去,当到达最大值时,无法增加非主分配区从而降低了效率。
    6. 对于小块的内存需要精确匹配,而对于large bin中则需要切割,多线程下由于不断的分割会产生很多内存碎片,对内存碎片的清理要加锁,会降低效率。

     

    转载于:https://www.cnblogs.com/zhangtiezi/p/8431621.html

    展开全文
  • ptmalloc源码剖析

    千次阅读 2019-03-31 10:14:43
    ptmalloc内存管理器 ptmalloc是glibc默认的内存管理器。我们常用的malloc和free就是由ptmalloc内存管理器提供的基础内存分配函数。ptmalloc有点像我们自己写的内存池,当我们通过malloc或者free函数来申请和释放...

    ptmalloc内存管理器

    ptmalloc是glibc默认的内存管理器。我们常用的malloc和free就是由ptmalloc内存管理器提供的基础内存分配函数。ptmalloc有点像我们自己写的内存池,当我们通过malloc或者free函数来申请和释放内存的时候,ptmalloc会将这些内存管理起来,并且通过一些策略来判断是否需要回收给操作系统。这样做的最大好处就是:让用户申请内存和释放内存的时候更加高效。(假如每次malloc都需要进行系统调用,开销就会很大)

    为了内存分配函数malloc的高效性,ptmalloc会预先向操作系统申请一块内存供用户使用,并且ptmalloc会将已经使用的和空闲的内存管理起来;当用户需要销毁内存free的时候,ptmalloc又会将回收的内存管理起来,根据实际情况是否回收给操作系统

    主分配区main_area非主分配区no_main_area

    ptmalloc的内存分配器中,为了解决多线程锁争夺问题,分为主分配区和非主分配区。

    1. 每个进程有一个主分配区,也可以允许有多个非主分配区。

    2. 主分配区可以使用brk和mmap来分配,而非主分配区只能使用mmap来映射内存块

    3. 非主分配区的数量一旦增加,则不会减少。

    4. 主分配区和非主分配区形成一个环形链表进行管理。

    使用中的chunk:

    空闲的chunk:

    空闲链表bins

    当用户使用free函数释放掉的内存,ptmalloc并不会马上交还给操作系统(这边很多时候我们明明执行了free函数,但是进程内存并没有回收就是这个原因),而是被ptmalloc本身的空闲链表bins管理起来了,这样当下次进程需要malloc一块内存的时候,ptmalloc就会从空闲的bins上寻找一块合适大小的内存块分配给用户使用。这样的好处可以避免频繁的系统调用,降低内存分配的开销。

    ptmalloc一共维护了128bin。每个bins都维护了大小相近的双向链表的chunk

    内存分配malloc流程

    1. 获取分配区的锁,防止多线程冲突。

    2. 计算出需要分配的内存的chunk实际大小。

    3. 判断chunk的大小,如果小于max_fast(64b),则取fast bins上去查询是否有适合的chunk,如果有则分配结束。

    4. chunk大小是否小于512B,如果是,则从small bins上去查找chunk,如果有合适的,则分配结束。

    5. 继续从 unsorted bins上查找。如果unsorted bins上只有一个chunk并且大于待分配的chunk,则进行切割,并且剩余的chunk继续扔回unsorted bins;如果unsorted bins上有大小和待分配chunk相等的,则返回,并从unsorted bins删除;如果unsorted bins中的某一chunk大小 属于small bins的范围,则放入small bins的头部;如果unsorted bins中的某一chunk大小 属于large bins的范围,则找到合适的位置放入。

    6. 从large bins中查找,找到链表头后,反向遍历此链表,直到找到第一个大小 大于待分配的chunk,然后进行切割,如果有余下的,则放入unsorted bin中去,分配则结束。

    7. 如果搜索fast bins和bins都没有找到合适的chunk,那么就需要操作top chunk来进行分配了(top chunk相当于分配区的剩余内存空间)。判断top chunk大小是否满足所需chunk的大小,如果是,则从top chunk中分出一块来。

    8. 如果top chunk也不能满足需求,则需要扩大top chunk。主分区上,如果分配的内存小于分配阈值(默认128k),则直接使用brk()分配一块内存;如果分配的内存大于分配阈值,则需要mmap来分配;非

    主分区上,则直接使用mmap来分配一块内存。通过mmap分配的内存,就会放入mmap chunk上,mmap chunk上的内存会直接回收给操作系统。

    内存释放free流程

    1. 获取分配区的锁,保证线程安全。

    2. 如果free的是空指针,则返回,什么都不做。

    3. 判断当前chunk是否是mmap映射区域映射的内存,如果是则直接munmap()释放这块内存。前面已使用chunk的数据结构中,我们可以看到有M来标识是否是mmap映射的内存。

    4. 判断chunk是否与top chunk相邻,如果相邻,则直接和top chunk合并(和top chunk相邻相当于和分配区中的空闲内存块相邻)。转到步骤8

    5. 如果chunk的大小大于max_fast(64b),则放入unsorted bin,并且检查是否有合并,有合并情况并且和top chunk相邻,则转到步骤8;没有合并情况则free。

    6. 如果chunk的大小小于 max_fast(64b),则直接放入fast bin,fast bin并没有改变chunk的状态。没有合并情况,则free;有合并情况,转到步骤7

    7. 在fast bin,如果当前chunk的下一个chunk也是空闲的,则将这两个chunk合并,放入unsorted bin上面。合并后的大小如果大于64KB,会触发进行fast bins的合并操作,fast bins中的chunk将被遍历,并与相邻的空闲chunk进行合并,合并后的chunk会被放到

    unsorted bin中,fast bin会变为空。合并后的chunk和topchunk相邻,则会合并到topchunk中。转到步骤8

    8. 判断top chunk的大小是否大于mmap收缩阈值(默认为128KB),如果是的话,对于主分配区,则会试图归还top chunk中的一部分给操作系统。free结束。

    使用注意事项

    为了避免Glibc内存暴增,需要注意:

    1. 后分配的内存先释放,因为ptmalloc收缩内存是从top chunk开始,如果与top chunk相邻的chunk不能释放,top chunk以下的chunk都无法释放

    2. Ptmalloc不适合用于管理长生命周期的内存,特别是持续不定期分配和释放长生命周期的内存,这将导致ptmalloc内存暴增。

    3. 多线程分阶段执行的程序不适合用ptmalloc,这种程序的内存更适合用内存池管理

    4. 尽量减少程序的线程数量和避免频繁分配/释放内存。频繁分配,会导致锁的竞争,最终导致非主分配区增加,内存碎片增高,并且性能降低。

    5. 防止内存泄露,ptmalloc对内存泄露是相当敏感的,根据它的内存收缩机制,如果与top chunk相邻的那个chunk没有回收,将导致top chunk一下很多的空闲内存都无法返回给操作系统。

    6. 防止程序分配过多内存,或是由于Glibc内存暴增,导致系统内存耗尽,程序因OOM被系统杀掉。预估程序可以使用的最大物理内存大小,配置系统的/proc/sys/vm/overcommit_memory,/proc/sys/vm/overcommit_ratio,以及使用ulimt –v限制程序能使用虚拟内存空间大小,防止程序因OOM被杀掉。

     

    展开全文
  • glibc_ptmalloc_learning
  • ptmalloc - 起步

    2017-05-24 21:56:16
    glibc下载和安装 调试ptmalloc
  • ptmalloc堆概述

    2018-05-10 14:42:04
    ptmalloc堆概述1 概述堆的概念在程序运行过程中,堆可以提供动态分配的内存,允许程序申请大小未知的内存。堆其实就是程序虚拟地址空间的一块连续的线性区域,它由低地址向高地址方向增长。 堆管理器我们一般称...
  • ptmalloc堆实现

    2018-05-10 15:08:05
    之后,glibc 中集成了ptmalloc2。 可以下载glibc源码查看ptmallochttp://ftp.gnu.org/gnu/glibc/ 查看glibc版本millionsky@ubuntu-16:~/tmp$ ldd --versionldd (Ubuntu GLIBC 2.23-0ubuntu9) 2.23 这里主要参考...
  • 前几年阅读过华庭的《glibc内存管理ptmalloc源代码分析》文章,并做过一篇笔记 今年打算重点阅读一下glibc里面,malloc部分的具体实现机制。 ptmalloc简介 Linux早期的版本,是由Doug Lea实现的,但是早期的版本...
  • ptmalloc内存分配机制

    2021-01-27 12:04:36
    堆的ptmalloc机制: https://www.cnblogs.com/P201521440001/p/9753693.html
  • Ptmalloc与Tcmalloc浅析

    2020-12-29 01:42:17
    Ptmalloc 内存分配 内存优化总结:ptmalloc、tcmalloc和jemalloc 内存释放 所有调用delete释放的内存,并不是立即调用brk(sbrk)归还给操作系统,而是先将这个内存块挂在free-list(bins)里面,然后进行内存归并(可选...
  • glibc内存管理ptmalloc源代码分析-电子资料-高清PDF版-pdf打印版
  • ptmalloc算法chunk简介

    2020-06-28 18:53:41
    本文主要介绍内存管理算法ptmalloc的内存管理单位–chunk的基本知识。
  • ptmalloc的实现细节

    2019-05-12 19:52:04
    如果对ptmalloc的基本设计还不熟悉,请先看:https://blog.csdn.net/songchuwang1868/article/details/89951543 一、bin数组 bin数组大体分成三个部分: 1、unsored bin数组 暂存一些没有排序的数据 unsored ...
  • ptmalloc的小总结

    2018-05-20 15:38:55
    关于ptmalloc的一些总结
  • PTmalloc hacking

    千次阅读 2012-11-27 22:38:21
    --[ CONTENTS  1 - Preface  2 - Introduction  2.1 - KiddieDbg Ptmalloc2  2.2 - SmallBin Corruption  2.2.1 - Triggering The HoL(e)  2.2.2 - A More Confusing

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,928
精华内容 771
关键字:

ptmalloc