接上一篇文章浅谈计算机中的存储模型(一)存储体系
这篇主要介绍物理内存
目录
- 物理内存
- 物理内存管理结构
- 位图
- 空闲区/空闲区链表
- 内存分配算法
- 首次适配
- 下次适配
- 最佳适配
- 最差适配
- 内存回收算法
- 内存回收的四种情况
- 内存碎片问题
- 内碎片
- 外碎片
- 紧缩技术
- 伙伴算法
- 物理内存管理结构
物理内存
物理内存其实就是我们机器的实际内存大小,比如我的笔记本电脑内存是4G。我们都知道程序是要加载道内存中才能执行,所以物理内存越大,我们电脑的性能就越好,以后会解释。
物理内存管理
我们知道程序要加载进入内存中才能执行,那么一个或多个进程进入内存如何给它划分大小呢,一般来说有两种技术,一个是将内存等长划分,然后选择一部分分给进程,另一个是不等长划分,进程需要多少给它划分多少。其中后面要说的分页机制是等长划分,分段机制则是不等长划分。分页就是将内存分为一块一块的结构,在虚拟内存中成为页,在物理内存中成为页框(页帧或内存块),分段则是逻辑上分为一段一段区域,大小不同。这里先简单描述下。
等长划分一般使用位图来管理
不等长划分一般使用空闲区表来管理
位图
位图(bitmap),其实就是用位来标记数据
在等长内存管理中,比如我们将内存等分为大小相同的内存块,那么一位标记一块,因为会形成一个位图。
如下:
这样,我们需要多大的块,只需要匹配bitmap中连续多少个0即可。
空闲区表
在不等长划分中,比如我们根据进程的大小来分配内存,这是就需要采用空闲区表来存储空闲的内存。
如下:
空闲区链表只不过是通过链式结构将空闲区表中的数据组织起来。
内存分配算法
上面说了我们如何通过数据结构来组织未分配的内存,我们以空闲区链表结构为例,下面来说说物理内存的分配算法,有如下四种。
首次适配算法
首次适配算法是在空闲区链表中从头开始查找符合申请内存大小的块,直到找到满足条件的为止,该算法不断的从头开始试验申请,所以大部分使用的都是低地址空间的内容,从而流出了高地址空间来满足大的申请需求,但是缺点是会在较低的地址空间中频繁的申请和释放导致低地址空间中的内存碎片,而且每次都查找都从头开始,查找效率比较低。
下次适配算法
下次适配算法是首次适配算法的一个改进,它每次从上一次适配的地方开始向下查找,不需要每次都从头开始,此算法使得内存使用均匀,但是不会有大的内存块来满足内存分配。
最佳适配算法
此算法先按照内存块的空闲区大小从小到大进行排序,排序后,每次从头开始匹配,这样匹配出来的结果肯定是最优的,但实际因为比较符合申请内存的大小,会出现很多较小的内存碎片无法使用,并且每次分配后都要重新排序,开销比较大。
最差适配算法
此算法按照内存块的空闲区从大到小进程排序,排序后,有进程申请内存时,将表头最大的内存块分配给它,这样如果不能分配则所有不能分配,且将大内存分配给它,若只占用一小部分还可以进行二次分配。
内存回收算法
内存分配且进程使用完后,我们要进行回收,一般而言,内存回收算法和内存的分配算法有着密切的关系。
所以我们仅仅看内存回收算法可能会出现的四种情况
内存回收的四种情况
左上为上相邻,右下相邻,左下是上下相邻,右下是上下不相邻。
内存碎片
什么是内存碎片,就是在内存中占据一定大小的空间却得不到利用的内存。内存碎片分为内碎片和外碎片
内碎片
内碎片:比如按页式分配等长,那么如果有一个进程需要5页多内存,那么我们只能给他分配6页内存,那么这第6页是未用完的,其中除过一些数据外,我们还有空闲的被该进程占据,其他进程也不能使用。这个成为内碎片
外碎片:外碎片是还未分出来的,未被进程占用且因为太小或其他不满足条件再次分配的小的内存块称为外碎片。
紧缩技术:我们一般采用紧缩技术来合并小的内存碎片,原理是将暂时不运行的进程安全的移动位置,独立出内存碎片,从而组装多个内存碎片合并成一个大的内存块。
注意的是有些进程并不能被移动,比如正在读写IO。
伙伴算法
伙伴算法是linux底层内存分配回收算法的一种实现。
本文只讲述伙伴算法的基本原理。
伙伴算法基本思想:
将内存大小变为二的n此方
如果一个程序申请的内存块大小 m 满足
2^n-1 < m < 2^n条件,那么就将此时的内存块分配给它。
如下图:
如上图,我们现在需要200K空间,1M等于1024K,如果m小于1M的一半,那么继续分离m,当分离到256时,刚好能满足200K的需求,所以分配。
归还时,采用内存回收算法的思想,看左右相邻。若没被占用则合并(也是为什么叫伙伴算法)。