内存分配方式及内存碎片
什么是内存碎片?
内部碎片的产生:因为所有的内存分配必须起始于可被 4、8 或 16 整除(视 处理器体系结构而定)的地址或者因为MMU的分页机制的限制,决定内存分配算法仅能把预定大小的内存块分配给客户。假设当某个客户请求一个 43 字节的内存块时,因为没有适合大小的内存,所以它可能会获得 44字节、48字节等稍大一点的字节,因此由所需大小四舍五入而产生的多余空间就叫内部碎片。
外部碎片的产生: 频繁的分配与回收物理页面会导致大量的、连续且小的页面块夹杂在已分配的页面中间,就会产生外部碎片。假 设有一块一共有100个单位的连续空闲内存空间,范围是0~99。如果你从中申请一块内存,如10个单位,那么申请出来的内存块就为0~9区间。这时候你 继续申请一块内存,比如说5个单位大,第二块得到的内存块就应该为10~14区间。如果你把第一块内存块释放,然后再申请一块大于10个单位的内存块,比 如说20个单位。因为刚被释放的内存块不能满足新的请求,所以只能从15开始分配出20个单位的内存块。现在整个内存空间的状态是0~9空闲,10~14 被占用,15~24被占用,25~99空闲。其中0~9就是一个内存碎片了。如果10~14一直被占用,而以后申请的空间都大于10个单位,那么0~9就 永远用不上了,变成外部碎片。
简单介绍程序内存分配方式:
内存分配方式主要有连续型分配方式和非连续型分配方式,顾名思义,连续型分配方式就是分配连续的空间,非连续型分配方式就是分配非连续的内存空间。
连续型分配内存方式:
单一连续分配:
最简单的分配方式,采用覆盖技术。优点是无外部碎片,缺点是只能用于单用户、有内部碎片、存储利用率低。
固定分区分配:
最简单的多道程序存储管理方式,它将用户内存空间划分为若干个固定大小(可以相等,也可以不等,同为4的倍数或其他),每个分区只装入一道作业。当有空闲分区的时候,就从作业队列里选择适当大小的作业装入该分区。为便于内存分配,通常将分区按大小排队,并为之建立一张分区说明表,其中各项包括每个分区的起始地址,大小及状态(是否被分配)。
无外部碎片,但是无法实现多进程共享一个主存区。
动态分区分配:
不预先划分内存,在程序装入内存时,根据进程的大小动态地建立分区,并使得分区的大小正好适合进程的需要,因此系统中分区的大小和数目是可变的。
动态分区分配内存方式刚开始是很好地,但是,之后会导致内存出现很多的小的内存块,也就是外部碎片。外部碎片可以通过紧凑来解决,就是操作系统不时地对进程进行移动和整理。但是需要动态重定位寄存器的支持。
动态分区分配在当系统有很大的内存块的时候,分配内存必须要有一个策略。
1)首次适应:地址递增,顺序查找,第一个能满足的即分配给进程。
2)最佳适应:容量递增,找到第一个能满足要求的空闲分区。
3)最坏适应:容量递减,找到第一个能满足要求的分区。
4)邻近适应:循环首次适应算法。
当一个进程发生缺页中断的时候,进程会陷入内核态,执行以下操作:
1、检查要访问的虚拟地址是否合法
2、查找/分配一个物理页
3、填充物理页内容(读取磁盘,或者直接置0,或者啥也不干)
4、建立映射关系(虚拟地址到物理地址)
重新执行发生缺页中断的那条指令
如果第3步,需要读取磁盘,那么这次缺页中断就是majflt,否则就是minflt。
内存分配的原理
从操作系统角度来看,进程分配内存有两种方式,分别由两个系统调用完成:brk和mmap(不考虑共享内存)。
1、brk是将数据段(.data)的最高地址指针_edata往高地址推;
2、mmap是在进程的虚拟地址空间中(堆和栈中间,称为文件映射区域的地方)找一块空闲的虚拟内存。
这两种方式分配的都是虚拟内存,没有分配物理内存。在第一次访问已分配的虚拟地址空间的时候,发生缺页中断,操作系统负责分配物理内存,然后建立虚拟内存和物理内存之间的映射关系。
在标准C库中,提供了malloc/free函数分配释放内存,这两个函数底层是由brk,mmap,munmap这些系统调用实现的。
下面以一个例子来说明内存分配的原理:
情况一、malloc小于128k的内存,使用brk分配内存,将_edata往高地址推(只分配虚拟空间,不对应物理内存(因此没有初始化),第一次读/写数据时,引起内核缺页中断,内核才分配对应的物理内存,然后虚拟地址空间建立映射关系),如下图:
2、进程调用A=malloc(30K)以后,内存空间如图2:
3、进程调用B=malloc(40K)以后,内存空间如图3。
情况二、malloc大于128k的内存,使用mmap分配内存,在堆和栈之间找一块空闲内存分配(对应独立内存,而且初始化为0),如下图:
5、进程调用D=malloc(100K)以后,内存空间如图5;
6、进程调用free(C)以后,C对应的虚拟内存和物理内存一起释放。
8、进程调用free(D)以后,如图8所示:
转载于:https://www.cnblogs.com/LUO77/p/5823982.html
内存分配方式及内存碎片相关推荐
- C/C++:程序的内存分配方式
转载自:http://ryansky.blog.51cto.com/187974/86286 1.内存分配方式 内存分配方式有三种: [1]从静态存储区域分配.内存在程序编译的时候就已经分配好,这块内 ...
- C/C++内存分配方式 .
1.内存分配方式 内存分配方式有三种: [1]从静态存储区域分配.内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在.例如全局变量,static变量. [2]在栈上创建.在执行函数时 ...
- C语言程序的内存分配方式
1.内存分配方式 内存分配方式有三种: [1]从静态存储区域分配.内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在.例如全局变量,static变量. [2]在栈上创建.在执行函数 ...
- C/C++ 内存分配方式,堆区,栈区,new/delete/malloc/free
内存分配方式有三种: [1] 从静态存储区域分配.内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在.例如全局变量, static 变量. [2] 在栈上创建.在执行函数时,函数内局 ...
- 内存分配方式以及堆和栈的区别
转载:https://blog.csdn.net/shanchangyi/article/details/51854795 对于一个程序要运行,涉及到的内存分配是一个首要问题,这里简单说一下一个简单的 ...
- C++内存分配方式、内存错误及其对策
C++内存分配方式.内存错误及其对策 内存分配方式有三种: 从静态存储区域分配.内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在.例如全局变量,static变量. 在栈上创建.在执 ...
- C++中内存分配方式、空指针及野指针的区别
一.C++中内存分配方式可以分为三种: (1)从静态存储区域分配: 内存在程序编译时就已经分配好,这块内存在程序的整个运行期间都存在.速度快.不容易出错,因为有系统会善后.例如全局变量,static变 ...
- MFC 教程【10_内存分配方式和调试机制 】
内存分配方式和调试机制 M内存分配 内存分配函数 MFCWin32或者C语言的内存分配API,有四种内存分配API可供使用. Win32的堆分配函数 每一个进程都可以使用堆分配函数创建一个私有的堆── ...
- Windows下动态内存分配方式http://whx.tzgt.gov.cn/newOperate/html/7/71/711/3938.html
这里的"动态内存"包含以下两个方面的内容: 1.内存.这里的"内存"指的是进程的虚拟内存空间.在Win32环境下,每一个进程拥有独立的,大小为4G(0x00 ...
- 内存分配方式及常见错误
内存操作对于程序开发人员来说,永远是一块雷区.在这片区域,总是不断的埋雷.排雷,而且往往是排雷花了非常大的代价.记得在公司实习时,有大概2个星期的时间,team的几个人去排雷--有地方发生了memor ...
最新文章
- webgl内置函数--通用函数
- 图论--SCC强连通缩点--Tarjan
- docker镜像创建与优化
- 71道经典Android面试题和答案
- scrapy 序列化写入器 ——ItemExporter
- cookie、session和application超详解说
- 活代码LINQ——08
- python学习day_04_字典
- ucinet数据集格式
- BAT文件中如何注释
- 《金字塔原理》要点汇总
- 管理者要做木匠,不要做医生”。木匠眼里,没有废料,每一块木材都有它的作用;而在医生眼里,没有完全健康的人,每个人都是病人
- Spring Boot在使用Gradle build命令卡住不动了
- 在网页前端调用exe程序并传参
- 实用自动化运维Python脚本
- win10激活出现错误0xc004C003
- 读书笔记:《谁说菜鸟不会数据分析-入门篇》第1-4章
- 如何创建一个带诊断工具的.NET镜像
- java图片与文字拼接
- @程序员:GitHub这个项目快薅羊毛