一,内存空间分布图

所以,mmap其实和堆一样,实际上可以说他们都是动态内存分配,但是严格来说mmap区域并不属于堆区,反而和堆区会争用虚拟地址空间。

这里要提到一个很重要的概念,内存的延迟分配,只有在真正访问一个地址的时候才建立这个地址的物理映射,这是Linux内存管理的基本思想。Linux内核在用户申请内存的时候,只是给它分配了一个线性区(也就是虚拟内存),并没有分配实际物理内存;只有当用户使用这块内存的时候,内核才会分配具体的物理页面给用户,这时候才占用宝贵的物理内存。内核释放物理页面是通过释放先行区,找到其对应的物理页面,将其全部释放的过程。

二,malloc 原理和内存碎片

下面以一个例子来说明内存分配的原理:

情况一、malloc小于128k的内存,使用brk分配内存,将_edata往高地址推(只分配虚拟空间,不对应物理内存(因此没有初始化),第一次读/写数据时,引起内核缺页中断,内核才分配对应的物理内存,然后虚拟地址空间建立映射关系),如下图:


1、进程启动的时候,其(虚拟)内存空间的初始布局如图1所示。
      其中,mmap内存映射文件是在堆和栈的中间(例如libc-2.2.93.so,其它数据文件等),为了简单起见,省略了内存映射文件。
      _edata指针(glibc里面定义)指向数据段的最高地址。 
2、
进程调用A=malloc(30K)以后,内存空间如图2:
      malloc函数会调用brk系统调用,将_edata指针往高地址推30K,就完成虚拟内存分配。
      你可能会问:只要把_edata+30K就完成内存分配了?
      事实是这样的,_edata+30K只是完成虚拟地址的分配,A这块内存现在还是没有物理页与之对应的,等到进程第一次读写A这块内存的时候,发生缺页中断,这个时候,内核才分配A这块内存对应的物理页。也就是说,如果用malloc分配了A这块内容,然后从来不访问它,那么,A对应的物理页是不会被分配的。 
3、
进程调用B=malloc(40K)以后,内存空间如图3。

情况二、malloc大于128k的内存,使用mmap分配内存,在堆和栈之间找一块空闲内存分配(对应独立内存,而且初始化为0),如下图:

4、进程调用C=malloc(200K)以后,内存空间如图4:
      默认情况下,malloc函数分配内存,如果请求内存大于128K(可由M_MMAP_THRESHOLD选项调节),那就不是去推_edata指针了,而是利用mmap系统调用,从堆和栈的中间分配一块虚拟内存。
      这样子做主要是因为::
      brk分配的内存需要等到高地址内存释放以后才能释放(例如,在B释放之前,A是不可能释放的,这就是内存碎片产生的原因,什么时候紧缩看下面),而mmap分配的内存可以单独释放。
      当然,还有其它的好处,也有坏处,再具体下去,有兴趣的同学可以去看glibc里面malloc的代码了。 
5、进程调用D=malloc(100K)以后,内存空间如图5;
6、进程调用free(C)以后,C对应的虚拟内存和物理内存一起释放。

7、进程调用free(B)以后,如图7所示:
        B对应的虚拟内存和物理内存都没有释放,因为只有一个_edata指针,如果往回推,那么D这块内存怎么办呢
当然,B这块内存,是可以重用的,如果这个时候再来一个40K的请求,那么malloc很可能就把B这块内存返回回去了
8、进程调用free(D)以后,如图8所示:
        B和D连接起来,变成一块140K的空闲内存。
9、默认情况下:
       当最高地址空间的空闲内存超过128K(可由M_TRIM_THRESHOLD选项调节)时,执行内存紧缩操作(trim)。在上一个步骤free的时候,发现最高地址空闲内存超过128K,于是内存紧缩,变成图9所示。

三,两个指针指向同一个内存空间

  释放内存,如free(),deleate(),只是做了一件事情:斩断指针变量与这块内存的关系。free函数就是把这块内存和指针之间的所有关系斩断。从此指针和那块内存之间再无瓜葛。至于指针变量本身保存的地址并没有改变,但是它对这个地址处的那块内存却已经没有所有权了。那块被释放的内存里面保存的值也没有改变,只是再也没有办法使用了。更斩草除根的办法是释放后马上悬空地址,即将指针置为NULL:将指针保存的地址清除,使其不指向任何内存。

虚拟空间,malloc的更多相关文章

  1. malloc原理和内存碎片[转]

    当一个进程发生缺页中断的时候,进程会陷入内核态,执行以下操作: 1.检查要访问的虚拟地址是否合法 2.查找/分配一个物理页 3.填充物理页内容(读取磁盘,或者直接置0,或者啥也不干) 4.建立映射关系 ...

  2. malloc原理和内存碎片

    当一个进程发生缺页中断的时候,进程会陷入内核态,执行以下操作: 1.检查要访问的虚拟地址是否合法 2.查找/分配一个物理页 3.填充物理页内容(读取磁盘,或者直接置0,或者啥也不干) 4.建立映射关系 ...

  3. 【转】malloc与free的底层实现

    本文转自:http://blog.163.com/xychenbaihu@yeah/blog/static/132229655201210975312473/ 如何查看进程发生缺页中断的次数? 用ps ...

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

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

  5. Linux malloc大内存的方法

    本博文为原创,遵循CC3.0协议,转载请注明出处:http://blog.csdn.net/lux_veritas/article/details/9963199 ------------------ ...

  6. Linux内存管理 (8)malloc

    专题:Linux内存管理专题 关键词:malloc.brk.VMA.VM_LOCK.normal page.special page. 每章问答: malloc()函数是C函数库封装的一个核心函数,对 ...

  7. Linux内存分配小结--malloc、brk、mmap【转】

    转自:https://blog.csdn.net/gfgdsg/article/details/42709943 http://blog.163.com/xychenbaihu@yeah/blog/s ...

  8. 【转】linux环境内存分配原理 malloc info

    Linux的虚拟内存管理有几个关键概念: Linux 虚拟地址空间如何分布?malloc和free是如何分配和释放内存?如何查看堆内内存的碎片情况?既然堆内内存brk和sbrk不能直接释放,为什么不全 ...

  9. malloc原理和内存碎片【转】

    转自:http://www.cnblogs.com/zhaoyl/p/3820852.html 当一个进程发生缺页中断的时候,进程会陷入内核态,执行以下操作: 1.检查要访问的虚拟地址是否合法 2.查 ...

随机推荐

  1. script利用src引用外部js文件,如果内部嵌套了js代码呢

    <script src='test.js' defer async> var a = 5; </script> 这个时候 var a = 5;会被忽略.

  2. 『Argparse』命令行解析

    一.基本用法 Python标准库推荐使用的命令行解析模块argparse 还有其他两个模块实现这一功能,getopt(等同于C语言中的getopt())和弃用的optparse.因为argparse是 ...

  3. IO模型--阻塞IO,非阻塞IO,IO多路复用,异步IO

    IO模型介绍: * blocking IO 阻塞IO * nonblocking IO 非阻塞IO * IO multiplexing IO多路复用 * signal driven IO 信号驱动IO ...

  4. 生成器yield

    #!/usr/bin/python#coding=utf-8'''Created on 2017年11月23日 from home @author: James zhan ''' def counte ...

  5. spoj mgame

    题解: f[i][j]表示先后手最大差 g[i][j]表示在最大差的时候是否有后手没得走 代码: #include<bits/stdc++.h> using namespace std; ...

  6. jq demo 轮播图,图片可调用,向左,自动+鼠标点击切换

    <!doctype html> <html> <head> <meta http-equiv="Content-Type" content ...

  7. 第十二次作业 - Beta答辩总结

    目录 前言 项目的链接与宣传 项目总结 原计划 达成情况 原因分析 [ Beta 冲刺博客链接汇总] [燃尽图] Beta版本展示 使用说明 视频展示 图片展示 答辩总结 [团队中个人的贡献比例] [ ...

  8. 马凯军201771010116《面向对象程序设计(java)》第七周学习总结

    理论与知识部分 多态性:概念:指在程序中同一符号在不同的情况下具有不同的解释.超类中定义的域或方法,被子类继承之后,可以具有不同的数据类型或表现出不同的行为.这使得同一域或方法在超类及各个子类中具有不 ...

  9. vscode下调试运行c++

    vscode是微软的最新产品,轻量易用,最初是前端用的多,尤其是typescript,因为vscode的作者也是typescipt作者.一般c++的IDE很多,比如visual studio等,但是都 ...

  10. thinkPHP 分页样式增加下拉列表

    $linkPage="  <select name='sldd' style='width:40px;height:30px;border:1px red block;' onchan ...