浅谈计算机内存管理之虚拟内存

前言

现在的机器都使用一种被称为虚拟内存的技术,这正是本文所谈论的主题,虚拟内存在面试中属于计算机操作系统部分,可以这么说来表明他的重要性,面试必会涉及操作系统部分,操作系统部分必会涉及虚拟内存。

内存管理

我们知道操作系统的作用在方向上分为两部分——管理资源和提供抽象。计算机有很多的资源,有输入输出设备、磁盘以及本文提到的内存。提供抽象的话,可以这么理解,计算机的所有设备都不一样,比如说各个厂家的鼠标、键盘和磁盘等,而操作系统提供抽象就是屏蔽这些差别,为上层提供一个统一的接口。
现在我们简单的了解了操作系统的功能,先在我们主要讲操作系统资源管理中的内存管理。在了解虚拟内存之前我们需要了解以下两个概念:

一、地址空间

地址空间其实就是对储存器的一个抽象,我们拿到的内存条、硬盘或者磁盘我们没有办法直接给它存储文件资料,它们就是一些被设计物理器件,不能直接使用,而操作系统需要对它们进行管理,就需要知道怎么将数据放在它们的头部怎么将数据放在尾部,所以操作系统在软件上引入地址空间的概念,也就是对每个存储设备命名,比如说32为寻址的机器上我要将数据一个字节的数据放在一块磁盘的第5个字节,只需要对0x00000005的地址空间各个比特位进行操作即可。

二、交换技术

我们知道计算机采用高速缓存机制,越高层CPU访问越快,同时价格也越贵。程序通常是储存在磁盘中,而磁盘的访问比较慢,所以程序运行是需要将执行语句或者数据加载到内存中,从而加快程序的运行速度。
但是嘞,内存容量往往是有限的,而程序的大小增长可根据需求不断的增大,于是出先了内存不够用的情况,这是就产生一种技术叫做“交换技术”。不把整个程序全部放入内存中,而是放一部分,把CPU需要用到的放在内存,内存中不需要的调回磁盘,需要和不需要好理解,调出和调入的实现下文再讲,现在我们只需要知道有这么一种技术。

三、虚拟内存

虚拟内存技术的诞生可以说是计算机技术成熟的标志,其诞生是因为CPU高速发展,而为CPU获取数据成为提高计算机并行的瓶颈,就这样业界大佬提出虚拟内存机制。
虚拟内存与地址空间一样都是为操作系统管理资源提供的一种抽象,地址空间是管理储存器,而虚拟内存是管理进程的一种抽象,虚拟内存技术为系统中的每一个进程提供一个虚拟地址,在程序编写时使用的都是虚拟地址,但是我们想象一下,CPU取数据肯定实在真实的物理地址上取啊,所以就需要把虚拟地址映射成真实的物理地址,再通过为每个CPU分配时间片,从而系统上的每个进程看起来都像是在独立的机器上运行,从而在一定程度上达到并行的目的。谨慎的人就会说——那也需要每个进程的数据和指令在内存中啊,感觉也没啥用啊。其实程序并不会将所有数据放在内存中,虚拟内存技术会把虚拟地址分成若干个页面,并通过一定的算法(下文会提到)并且利用交换技术将程序经常用到的页面放到内存。有了这样的大体了解,下面我们讲一些重要技术。

分页技术

前面我们已经提到,要实现并行不可能将所有程序需要的东西都放在内存中,即使是放一个程序内存也可能容纳不了,所以就允许每个进程将常用的放如内存,而现在我们提到的分页技术就是通过系统权衡,将进程(程序)的所有指令啊,数据等等分成一个个等大的容量,称为页面,从描述中可知,页面的叫法实在虚拟内存中,那么虚拟内存的东西都有可能放在物理内存中啊,所以很容易得知物理内存应该与虚拟内存的页面等大就刚好匹配,然而大多数情况就是这样(当然也有特殊情况,这里不讨论),而物理内存的这些单位称为页框。
现在我你应该大致了解了分页,现在我们来了解这个技术的重要细节。
首先,虚拟地址是怎么映射成为物理地址的呢?在没有虚拟内存的系统上地址直接被送到总线上,并不需要映射,这我相信都能够理解,而在有虚拟内存的系统上,虚拟地址首先被送到内存管理单元(Memory Management Unit),下文称MMU。通过MMU,CPU可以顺利寻址。MMU的作用如图所示:
MMU作为核心单元示意

第二,不是说只有一部分程序需要的东西在内存吗?如果寻址的东西刚好不在怎么办呢?当出现这种情况的时候,MMU察觉到这种情况,就会产生一种缺页中断或者叫做缺页错误从而使CPU陷入内核,然后操作系统查找一个合适的页面换出,使引发缺页的指令涉及到的数据的页面存放到内存。
第三、MMU是如何工作的呢?MMU内部维护一个数据结构,称为页表,页表由若干页表项组成,页表项中包含很多的信息,比如说所请求的页面在不在内存、从虚拟地址到物理地址的引索表、记录页面是否被修改、保护位以及高速缓存禁止位等等。
第四、感觉将虚拟地址送到MMU(需要访问内存)再寻址也费时,有没有更直接的方法?有的计算机存在一个小的硬件设备,能够将虚拟地址直接映射成物理地址,这种设备成为转换检测缓冲区(Translation Lookaside Buffer),简称TLB,有称快表。
第五、程序的增长只要人们愿意是可以无限增长的,(远远大于内存),这可能存在这么一种情况页表不能容纳虚拟内存,这是有两种方法解决:一是多级页表;二是倒排表。由于篇幅关系自行了解。

页面置换算法

从上文“分页技术”可知当虚拟内存所映射到的数据不在内存时就会发生一个缺页中断,之后陷入内核,通过系统调用把引发缺页中断的页面调到物理内存中,那么应该把哪一个页面写入磁盘,从而让需要的页面调进来嘞?这时就和我们这部分的主题“页面置换算法”有关了。我们知道,我们可以理解“缺页中断”是一个错误,产生了错误就需要花费时间去弥补,又要调用磁盘驱动去读写数据,现在有了硬盘速度是快了许多,以前的机械盘就需要花费较多的时间。由此可见——页面置换算法可以直接决定系统的性能。这个应该不难理解。下面我们将简单的描述一些常见的页面置换算法。

一、最优页面置换算法

听名字就知道它是最优的,但是嘞它有一个唯一的缺点,我先描述一下这个算法,再来看看它的缺点是什么。
最优算法要为每一个页面标记在多少此指令之后执行,而每次置换标记数大的,也就是将执行靠最后的置换出来。
简单吧,缺点在哪里呢?细心的读者可能就发现了,程序并不是按照指定的路线运行的,很多跳转语句,从而实行起来的难度很大,至少现在还没有方法。那么它存在有什么意义呢?它是用来衡量其它算法的优良,也可以用来定义理想算法。

二、最近未使用页面置换算法

我们知道页表中的表项记录许多的信息,其中就包括了是否被访问,是否别修改,如果修改了就将R(读)和M(写)置1,读取就将R位置1,这些都是由硬件来完成的的。当缺页中断发生时,页表项根据这两个位可以分成四类:
0、R(0) M(0)
1、R(0) M(1)
2、R(1) M(0)
3、R(1) M(1)
这时总感觉第二种没有可能,其实系统维护一个时钟,到点就会产生一个中断,利用硬件将R位清零。这时候就有可能了。每次发生缺页中断就会置换出编号小的,这是我们就明白了“最近未使用页面算”的这个最近是多久了,一个时钟滴答。这就是最近未使用算法(NRU)。

三、先进先出页面置换算法

这个很好理解,就和队列一样,聪明的你相信不用我多讲。确定的话很可能会淘汰一些常用的界面,因此很少会使用单纯的先进先出算法(FIFO)。

四、第二次机会页面置换算法

这个算法是FIFO的升级版,当产生缺页中断时检查旧的页面,如果最近访问过(R(1))就置零R,并将它放到队尾修改他的入队时间。这个算法一定程度上改善了FIFO。

五、时钟页面算法

第二次机会算法时比较合理的,但是每一次从头访问链表是比较浪费资源的,因此就构造一个环形链表,当缺页中断产生使就检查指针指向的页表项若R为0就将该页面淘汰,指针移到下一项,若为1那就向前移动,直到找到一个合适的项。

六、最近最少使用页面置换算法

这个算法是这样描述的,在缺页中断发生时,置换出未使用时间最长的的页面,也就是最近最少使用页面置换算法(LRU)。
那么这个算法是怎样实现的呢?在内存中维护一个所有在内存中的链表,将使用最多的放在链表头,使用最少的放在链表尾,当缺页发生时,直接把尾部的页面置换出,然而没事使用页面都需要重新计算页表的位置,因此开销比较大。

七、工作集页面置换算法

首先我们了解以下“工作集”,即一个进程正在使用的页面的集合。可以这样来理解,使用这个页面以及接下来一段时间将要使用的页面的集合,从这里我们能够知道工作集时随时间变化而变化的,为了实现工作集模型,操作系统必须跟踪哪些页面在工作集中,确定工作集则是该算法的重点,现在普遍的方法是在多少时间内使用过的未工作集成员,在这里我们假设是x秒,该算法需要用到两个页表项的内容访问位R和上次使用的时间,当发生缺页中断时,系统就会扫描整个页表,同样的R位在每个时钟滴答也会被清零。在扫描整个页表时若R为1,则说明在这个时钟滴答内被访问过,输入工作集成员,并把上次使用时间改为当前时间。若R为0,则比较生存时间和x的大小若大于则说明不在工作集内,小于则在,并记住上次使用的最小时间以方便当所有页面都在工作集时移除上次使用时间最小的页面。

八、工作集时钟页面置换算法

该算法是时钟算法和工作集页面算法的结合,由于实现简单,性能较好,得到了观广泛的应用。
下面讲以下实现的原理,和工作集页面置换算法一样需要用到页表项中的R位,和上次使用时间,在内存中所有的页面围成一个循环表并且有一个指针,当发生缺页中断时,检查指向的页面,若该页面的R位为1,则将R为置0移向下个页面,当R位为0则则比较生存时间和x判断是否在工作集,若在则移向下一个页面,不在则确定页面是否被修改,若无改动则将其移除,若有修改则移向下一位,判断有无修改是减少磁盘写回造成的进程切换。

页面置换算法总结

页面置换算法直接关系到性能问题,所以他的重要性相信大家不言而喻。总之,该算法就是要做两件事:
一、尽量避免缺页中断。
二、当缺页中断发生时去处理。
总之在上面的算法中工作集时钟置换算法在实现方面和性能方面都很好,是需要重点掌握的!

分段技术

我们知道虚拟内存中程序的资源放置地址是有规定的,如程序正文放置在底部还是顶部,常量表放置在哪里,往哪个方向增长。也就是各个部分是跌在一起的,如果是需要增长的部分,如:堆栈,会预留空间,这就有一个问题,当预留的空间使用完了怎么办?解决问题的方法是使用分段技术,程序的资源由许多的段组成,每个段相互独立,地址由0到某个最大值,并且段的大小在运行是会动态的改变,所以它们会独立的增长而不影响其它的段,其实段也可被装满,只是这个空间通常情况下都会很大,因此很少会发生。
分段该有其它的优点,如简化过程链接、简化进程之间共享过程和数据(只需要将数据放置在一个段中,这比分页实现起来简便很多)。
分页能使程序需要的资源出现在内存,暂时不需要的写回磁盘,而分段使得易于编程、模块化,保护和共享,而现代机器则是将两者结合。从而使得性能和管理最大化,至于实现的技术与本文主题不符,请自行查阅资料。

总结

虚拟内存技术可以说是计算最成功的抽象技术之一,不但使用了更大的线性空间而不用装备更大的储存器,而且还使得系统能更好的管理进程,也方便了程序间共享数据。
本次分享就到这里了,希望大家喜欢。
如有疑问欢迎提问,如有错误欢迎指正。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值