虚拟内存实现方式

简介 在很久很久以前,那时候程序的地址操作都是直接针对物理地址的。但是不难想到,这种方式存在很多的问题。
首先,程序员直接操纵物理地址可能导致很多未知的灾难,例如:程序将指针指到了操作系统所占的地址上,并进行了操作。这种操作很可能直接引起操作系统崩溃。
第二点,设想在有两个程序同时装入内存的情形,编译器在编译第二个程序的代码时是无法了解到内存中已经存在一个程序的。所以第二个程序的物理地址和第一个程序的物理地址可能有重叠的情况。有的同学可能要是,那我把第二个程序重定位一下不就行了么。历史上确实出现过这种做法,经典做法是为CPU加上一个基址寄存器和界限寄存器。重定位确实解决了一些问题,但他又会产生新的问题。重定位的加法造成了载入速率过慢问题,在多个程序载入延迟的积累下拖沓的时间就很可观了。
那直接访问物理地址的问题这么多,有什么解决方法吗?当你提出这个问题的时候,虚拟内存这个概念就自然而然的出来了。
说虚拟内存机制之前我还要插一句题外话,不知道大家还记不记得我们的多道程序设计方式的思想。多道程序设计并不是说CPU可以同时处理多个程序运算了。每个程序确实独占一个CPU,不过确是逻辑上的CPU。此话怎讲?CPU还有逻辑CPU,老师上课咋没说过嘞!其实,逻辑CPU是指每个程序在运行的时候都以为自己所占用的,是CPU的全部资源,然而它并不知道再他被中断挂起的时候CPU又去偷偷运行别的程序了(怎么描述起来怪怪的,咳咳)。所以说,在一个进程运行的时候他以为自己拥有完整的CPU,其实并不是这样的。虚拟内存机制也是这个道理。每一个程序在内存中运行时,他以为自己拥有者全部的内存,比如你的内存是4G的,它就以为自己拥有4G的内存。但我们明白,它以为永远都是它以为的,程序最终还是要在硬件上跑的,这时候我们就需要一个转换机制,将虚拟地址转换为物理地址。一涉及到计算,当然就轮到我们的CPU大哥出马了。CPU中有个硬件叫做MMU(Memory Manager Unit 内存管理单元),他的作用就是将我们的虚拟地址转换为物理地址。我们到底该怎么转换呢?这时候就得引入 一些新的概念了。页面、页框、页表、缺页中断和TLB。下面让我们来一一看看这些名词的意思和作用~
页面和页框 【虚拟内存实现方式】我们来打个比方,假设你现在有一台32KB内存的电脑,虚拟内存是64KB。首先我们先将64KB的虚拟内存切个片,一个片大小为4KB,所以总共切了16片。同时,把32KB的物理内存也按4KB的切片,总共切了8片。那么我们就称虚拟内存的一个片叫做页面,物理内存的一个片叫做页框。
页表 同学们可能已经猜到了,没错,虚拟内存和物理内存之间是有一个映射关系的。这个映射该怎么实现呢,这就需要我们页表的登场啦!页表中维护着页表和页框的对应关系。举个栗子,一个地址为0x0010000000000100的16位地址。16位地址可拆分为两部分,前4位和后12位。前4位对应着16个虚拟页表的号牌用于在页表中寻找对应的页框号,后12位用于页内偏址。0010即是2号,我们在页表中查找2号选手对应的页框,假设是100。那么我们虚拟地址所对应的物理地址即可得出,为100+之前的后12位页内偏移地址,即0x100000000000100。
不过毕竟页面比页框为16:8,那么肯定会有一部分的页面没有所对应的页框,如果我们的虚拟地址就在这些页面中我们该怎么办呢?
缺页中断 没错,如果我们的虚拟地址所在页面没有对应的页框,那么系统会产生一个缺页中断。缺页中断使CPU停下手头的工作,转而去寻找一个使用最少的一个页框,将其写入到磁盘中(如果页框范围内地址的内容有改变的话,没有改变则不需要写入磁盘)。然后修改将页面指向该页框,修改映射关系,至此缺页中断处理结束。CPU继续执行之前的工作。
TLB 到这里,虚拟内存已经可以完整的映射到物理内存了,但还有一些问题。那就是速度问题。我们设想一下,如果把页表存储在进程中,那么每次CPU都得进入内存中查询,非常的影响速度。那我们如果设置一个寄存器在CPU中,那速度不就很快了么?确实这样CPU的访问速度会非常的快,但是每次的进程切换,都会有新的页表载入该寄存器中,同样非常影响速度。那我们就没有办法了么?根据计算机科学家的统计,其实有一些页面映射是非常频繁的,而剩余的映射则非常少,那么我们就可以将这些映射最频繁的页面放入CPU寄存器中,而这个CPU寄存器我们就叫他TLB。
码字不易,如果喜欢的话就加一下收藏吧,后续还会有更新哦~

    推荐阅读