您当前的位置:首页 > 电脑百科 > 程序开发 > 编程百科

为什么会产生内存碎片?

时间:2019-08-28 13:16:41  来源:  作者:

来源:微信公众号:cpp软件架构

要想回答这个问题,就得刨根问底,内存到底是怎样分配的?

在内核态的角度来看,进程需要分配内存的方式有两种:brk和mmap这两个系统调用

  1. brk是数据段的最高地址指针_edata往高地址增长;
  2. mmap是建立了页到用户进程的虚拟空间映射,在进程的虚拟地址空间中,堆和栈之间的大空间中找一块空闲的地址。

这两种方式分配到的都是虚拟内存,并还没有分配真正的物理地址。会在第一次访问的时候,内核判断有没有物理地址,如果没有回发生缺页中断,然后分配物理地址,建立虚拟地址和物理地址之间的映射关系。

但在用户态申请动态内存,是不会直接调用这两个系统调用接口。一般情况下是通过C库的malloc/free来申请和释放。而C库的实现也正是基于这两个系统调用接口,进行上层的封装和管理。

当内核发生缺页中断的时候,到底会做哪些事情呢?

首先进程会从用户态陷入到内核态运行,会执行以下步骤:

  1. 检查需要访问的虚拟地址是否合法;
  2. 查找,分配物理页;
  3. 填充物理页的内容;
  4. 建立映射关系(虚拟地址->物理地址);

重新执行发生缺页中断的那条指令。

如果第3步,需要读取磁盘,那么这次缺页中断就是majflt,否则就是minflt

注意:

用ps -o majflt,minflt -C program命令查看。

majflt代表major fault,中文名叫主错误,minflt代表minor fault,中文名叫次错误。

这两个数值表示一个进程自启动以来所发生的缺页中断的次数。

下面我们用实例来解释下内存申请的原理

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

 

为什么会产生内存碎片?

 

 

1、进程启动的时候,其(虚拟)内存空间的初始布局如第一幅图所示。其中,mmap内存映射文件是在堆和栈的中间(例如libc-2.2.93.so,其它数据文件等),为了简单起见,省略了内存映射文件。_edata指针(glibc里面定义)指向数据段的最高地址。

2、进程调用A=malloc(30K)以后,内存空间如第二幅图:malloc函数会调用brk系统调用,将_edata指针往高地址推30K,就完成虚拟内存分配。你可能会问:只要把_edata+30K就完成内存分配了?

事实是这样的,_edata+30K只是完成虚拟地址的分配,A这块内存现在还是没有物理页与之对应的,等到进程第一次读写A这块内存的时候,发生缺页中断,这个时候,内核才分配A这块内存对应的物理页。也就是说,如果用malloc分配了A这块内容,然后从来不访问它,那么,A对应的物理页是不会被分配的。

3、进程调用B=malloc(40K)以后,内存空间如第三幅图。

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

 

为什么会产生内存碎片?

 

 

4、进程调用C=malloc(200K)以后,内存空间第一幅图:默认情况下,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)以后,如第一幅图所示:B对应的虚拟内存和物理内存都没有释放,因为只有一个_edata指针,如果往回推,那么D这块内存怎么办呢

当然,B这块内存,是可以重用的,如果这个时候再来一个40K的请求,那么malloc很可能就把B这块内存返回回去了

8、进程调用free(D)以后,如第二幅图所示:B和D连接起来,变成一块140K的空闲内存。

9、默认情况下:当最高地址空间的空闲内存超过128K(可由M_TRIM_THRESHOLD选项调节)时,执行内存紧缩操作(trim)。在上一个步骤free的时候,发现最高地址空闲内存超过128K,于是内存紧缩,变成第三幅图所示。

如果这个时候我们想要申请一块50K的内存E,就会出现下图的情况。

 

为什么会产生内存碎片?

 

有没有发现,并没有从中间40K的内存分配,因为不满足我们申请50K大小的要求,而是向下偏移指针_edata分配50K,到这里就能发现就产生了内存碎片,这块碎片正是那40K。

系统运行的越久,出现上述这样的情况越多,整个系统的小内存就会很多,导致的结果是:查看系统的剩余内存比较可观,但申请大块内存会返回失败。



Tags:内存碎片   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
内存碎片的产生与对数据进行的操作,数据的特点等有关,与使用的内存分配器也有关。如果redis服务器的内存碎片很大,可以通过安全重启的方式减少内存碎片,重启后,redis重新从备份文...【详细内容】
2020-07-31  Tags: 内存碎片  点击:(87)  评论:(0)  加入收藏
要想回答这个问题,就得刨根问底,内存到底是怎样分配的?...【详细内容】
2019-08-28  Tags: 内存碎片  点击:(279)  评论:(0)  加入收藏
▌简易百科推荐
本文分为三个等级自顶向下地分析了glibc中内存分配与回收的过程。本文不过度关注细节,因此只是分别从arena层次、bin层次、chunk层次进行图解,而不涉及有关指针的具体操作。前...【详细内容】
2021-12-28  linux技术栈    Tags:glibc   点击:(3)  评论:(0)  加入收藏
摘 要 (OF作品展示)OF之前介绍了用python实现数据可视化、数据分析及一些小项目,但基本都是后端的知识。想要做一个好看的可视化大屏,我们还要学一些前端的知识(vue),网上有很多比...【详细内容】
2021-12-27  项目与数据管理    Tags:Vue   点击:(2)  评论:(0)  加入收藏
程序是如何被执行的  程序是如何被执行的?许多开发者可能也没法回答这个问题,大多数人更注重的是如何编写程序,却不会太注意编写好的程序是如何被运行,这并不是一个好...【详细内容】
2021-12-23  IT学习日记    Tags:程序   点击:(9)  评论:(0)  加入收藏
阅读收获✔️1. 了解单点登录实现原理✔️2. 掌握快速使用xxl-sso接入单点登录功能一、早期的多系统登录解决方案 单系统登录解决方案的核心是cookie,cookie携带会话id在浏览器...【详细内容】
2021-12-23  程序yuan    Tags:单点登录(   点击:(8)  评论:(0)  加入收藏
下载Eclipse RCP IDE如果你电脑上还没有安装Eclipse,那么请到这里下载对应版本的软件进行安装。具体的安装步骤就不在这赘述了。创建第一个标准Eclipse RCP应用(总共分为六步)1...【详细内容】
2021-12-22  阿福ChrisYuan    Tags:RCP应用   点击:(7)  评论:(0)  加入收藏
今天想简单聊一聊 Token 的 Value Capture,就是币的价值问题。首先说明啊,这个话题包含的内容非常之光,Token 的经济学设计也可以包含诸多问题,所以几乎不可能把这个问题说的清...【详细内容】
2021-12-21  唐少华TSH    Tags:Token   点击:(10)  评论:(0)  加入收藏
实现效果:假如有10条数据,分组展示,默认在当前页面展示4个,点击换一批,从第5个开始继续展示,到最后一组,再重新返回到第一组 data() { return { qList: [], //处理后...【详细内容】
2021-12-17  Mason程    Tags:VUE   点击:(14)  评论:(0)  加入收藏
什么是性能调优?(what) 为什么需要性能调优?(why) 什么时候需要性能调优?(when) 什么地方需要性能调优?(where) 什么时候来进行性能调优?(who) 怎么样进行性能调优?(How) 硬件配...【详细内容】
2021-12-16  软件测试小p    Tags:性能调优   点击:(20)  评论:(0)  加入收藏
Tasker 是一款适用于 Android 设备的高级自动化应用,它可以通过脚本让重复性的操作自动运行,提高效率。 不知道从哪里听说的抖音 app 会导致 OLED 屏幕烧屏。于是就现学现卖,自...【详细内容】
2021-12-15  ITBang    Tags:抖音防烧屏   点击:(25)  评论:(0)  加入收藏
11 月 23 日,Rust Moderation Team(审核团队)在 GitHub 上发布了辞职公告,即刻生效。根据公告,审核团队集体辞职是为了抗议 Rust 核心团队(Core team)在执行社区行为准则和标准上...【详细内容】
2021-12-15  InfoQ    Tags:Rust   点击:(25)  评论:(0)  加入收藏
相关文章
    无相关信息
最新更新
栏目热门
栏目头条