zoukankan      html  css  js  c++  java
  • malloc内存分配与free内存释放的原理

    malloc内存分配与free内存释放的原理

    前段时间一直想看malloc的原理,在搜了好几篇malloc源码后遂放弃,晦涩难懂。

      后来室友买了本深入理解计算机系统的书,原来上面有讲malloc的原理,遂看了,先明白理论,在看代码就理解比较快了= =

      1.问题的引入:

       为什么要使用malloc,主要是因为在代码中,为了节约内存,很多数据都是动态生成的,所以会用malloc,对应于C++中的new,底层还是调用malloc.

      2.碎片的问题:

       会有内部碎片与外部碎片的问题,内部碎片难以消除(因为字对齐之类的问题),而外部碎片是可以消除的(如果不消除的话,外部的内存块越来越小,虽然数量多了,但是利用率会急剧下降!)

      3.需要解决的问题:

      

      4.隐式的空闲链表:

      一个简单的堆块,这里只有头部,下面为了优化,还会使用尾部。

      

      隐式的空闲链表:

      

      这样就把用链表的方法把堆空间给联系起来了。特点明显,实现简单,但分配时查询空堆块是线性时间的。

      5.放置以分配的块:

        1)、首次适配:从链表开始寻找适合的空堆块,直到找到为止

        2)、下一次适配:从上一次的分配点开始找,直到找到适合的空堆块为止

        3)、最佳适配:查询整个链表,找到最合适(浪费最小)的空堆块

      6.分割空闲块:

        当前的分配的空堆块比所需要的空间大很多的时候,如果不分割,就会照成内部碎片过大,利用率下降。

        当需要3个字节的空间时,首次适配找到了满足条件的第二个堆块,但堆块过大,所以分割成两个16字节的堆块。

        

      7.获取额外的堆存储器:

       当链表中不能满足申请要求的堆块空间的时候,1)通过合并相邻的堆块空间,形成单个尽量大的堆块空间 2)实在没有其他办法了,分配器通过sbrk函数向内核申请格外的堆空间,分配器将堆空间插入到链表中,然后提供给申请空间的块。

      8.合并

      

      如果,在如上的情况下,合并两个块,由于当前块不知道上一个块的情况,它要通过遍历整个链表才能知道上一个堆块的空间是否为空,这样将花费线性的时间来合并与当前相邻的空闲堆块。有个类似双向链表的方法(不过不是真正的双向链表,只是可以加一个信息量,直接就可以知道上一个堆块的情况)

      

      上一个堆块的情况就容易知道了,下面有四种情况:

      

      

      这样,堆块合并的问题就解决了。

    参考:深入理解计算机系统

     
     
  • 相关阅读:
    arthas-常用命令
    k8s-容器技术-Mount Namespace
    k8s-statefulset介绍
    k8s-yaml配置文件
    k8s-控制器模式
    k8s-pod使用
    k8s-pod简介(半原创)
    k8s-安装我们第一个集群
    k8s-安装
    Corn表达式详解(转)
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3456714.html
Copyright © 2011-2022 走看看