在计算机系统中,多个进程之间共享CPU和内容,如果太多的进程需要过多的内存空间那么其中一部分进程金辉因为无法获得足够的内存空间而无法运行。除此之外,如果某一个进程不小心把数据写入到另外一个进程的数据空间中,那么就会出现令人疑惑的错误。为了有效的管理内存,现代计算机系统提供了对内存的一种抽象概念,叫做虚拟内存。虚拟内存是计算机系统中一个非常重要的概念,它可以自动完成内存管理的相关操作,并不需要应用程序员来人为干扰。
学习虚拟内存的原因:
- (1)虚拟内存是核心,虚拟内存遍及到计算机系统的各个层面,在硬件异常,链接器,汇编器,加载器,文件,以及进程的设计中都扮演了重要的角色,理解好虚拟内存可以帮助我们更好的理解计算机是如何工作的。
- (2)虚拟内存是强大的,可以为应用程序提供强大的能力,编写应用程序时可以利用虚拟内存提供的特性。
- (3)虚拟内存是危险的,当我们编写代码时,每次引用一个变量,使用一个指针或者调用一次malloc函数时都会和虚拟内存发生交互。如果虚拟内存使用不当,会发生非常复杂的错误。
物理地址、
计算机系统中主存被看成一个M个字节大小的大数组。每个字节都有一个唯一的物理地址。
虚拟地址、
虚拟地址是虚拟的,CPU通过MMU(内存管理单元——利用主存中的查询表动态翻译虚拟地址 )硬件将虚拟地址转化为物理地址,流程如图:

早期的计算机系统使用物理寻址的方式,CPU使用物理地址直接访问内存。现代计算机使用虚拟寻址方式。
如图展示了CPU访问虚拟地址4100,经过了MMU转化成物理地址4,然后读取起始地址为4的连续4个字节,返回到CPU内。
地址空间、
地址空间是一个非负整数的有序集合。如果地址空间中的整数是连续的,我们就说它是一个线性地址空间。一个地址空间的大小是由表示最大地址所需要的位数来表示的,例如64位地址,最大为2^64个。
虚拟,物理地址空间、
虚拟地址空间不同于物理地址空间,一般来说虚拟地址空间大小大于物理地址空间大小。例如现代的x86系统上,理论上虚拟地址空间大小为2^64。物理地址空间大小对应着真实的内存条容量大小,例如我的内存条大小为16G,那么物理空间大小为16*1024*1024*1024。
为什么要使用虚拟内存,MMU?
SRAM(静态随机访问存储器): L1 Cache,L2 Cache,L3 Cache
DRAM(动态随机访问存储器) :main memory
SRAM比DRAM快大约10倍,而DRAM比磁盘块大约10万倍。所以DRAM缓存不命中比SRAM缓存不命中对程序的执行影响更大。当DRAM缓存不命中时,需要从磁盘读取数据到内存,因此耽误的时间比较长,所以就需要使用虚拟内存来做磁盘的缓存。

有三个重要的原因:
- (1)虚拟内存使用DRAM作为存储在磁盘上的实际数据的缓存,可以将虚拟内存视作为存储在磁盘上的数据的DRAM缓存,这使我们能够更有效的使用内存,因为我们只需要缓存经常使用的数据。因此通过仅使用虚拟地址空间的一部分,我们可以更有效的使用内存,仅仅将虚拟地址空间的一部分实际存储在物理存储器中。
- (2)大大简化了内存管理。虚拟地址空间对于每个进程来说都是相同的,代码以及数据总是加载到固定的地址,堆栈位于用户可见地址空间的顶部,但实际上与那些地址相对应的内容分布在整个内存中。
- (3)允许我们对访问内存进行保护,每一个进程都有独立的虚拟地址空间,这可以防止其他进程访问,虚拟内存允许我们创建这些单独的受保护的私有地址空间。
虚拟内存做缓存工具、
概念上而言,虚拟内存(VM)被组织为一个由存放在磁盘上的 N 个连续的字节大小的单元组成的数组。,其中每个字节都有唯一的虚拟地址,这个虚拟地址就是数组的索引值。虚拟内存系统通过将虚拟内存分割为虚拟页的大小固定的块来处理这个问题。物理内存和虚拟内存被分割为物理页和虚拟页,大小都是P字节,物理页也称之为页帧。
(1)虚拟页面的集合都分为三个不相交的子集:
- 未分配的:VM系统还没有分配(创建)的页。未分配块没有它们的任何数据和它们关联,也不占磁盘空间。
- 已缓存的:当前已经缓存在物理内存的已分配页
- 未缓存的:未缓存在物理内存的已分配页

(2) 页表
页表将虚拟页映射到物理页。每次地址翻译硬件将虚拟地址转换为物理地址时都会读取页表。操作系统负责维护页表的内容,以及在磁盘与DRAM之间来回传送页。
通过页表,虚拟内存系统可以判定一个虚拟页是否存放在DRAM中的某个地方。如果是,系统还必须确定这个虚拟页放在哪个物理页中。如果不命中,系统必须判断这个虚拟页存放在磁盘的哪个位置。
在物理存储中选择一个牺牲页,并将虚拟页从磁盘拷贝到DRAM中,替换这个牺牲页。
这些功能是由许多软硬件联合提供的,包括操作系统软件、MMU(存储器管理单元)中的地址翻译硬件和一个存放在物理存储器中的叫做页表的数据结构。
页表是页表条目(Page Table Entry, PTE)的一个数组;每个PTE是由一个有效位和一个n位地址字段构成的;有效位表明当前虚拟页是否缓存在DRAM中;地址字段表明DRAM中相应的物理页起始位置。
如果没有设置有效位,空地址表示虚拟页还没有被分配;否则这个地址指向虚拟页在磁盘上的起始位置。(虚拟页映射到磁盘中不叫缓存)。

(3)页命中
当页表中存在对虚拟地址空间中的字引用时,会发生页面命中。

(4)缺页
在虚拟内存的习惯说法中,DRAM 缓存不命中称为缺页(page fault)。
CPU 引用了 VP 3 中的一个字,VP 3 并未缓存在 DRAM 中。地址翻译硬件从内存中读取 PTE 3,从有效位推断出 VP 3 未被缓存,并且触发一个缺页异常。缺页异常调用内核中的缺页异常处理程序,该程序会选择一个牺牲页,在此例中就是存放在 PP 3 中的 VP 4。如果 VP 4 已经被修改了,那么内核就会将它复制回磁盘。无论哪种情况,内核都会修改 VP 4 的页表条目,反映出 VP 4 不再缓存在主存中这一事实。下面这张图是缺页前。

对 VP3 中的字的引用会不命中,从而触发了缺页。接下来,内核从磁盘复制 VP 3 到内存中的 PP 3,更新 PTE 3,随后返回。当异常处理程序返回时,它会重新启动导致缺页的指令,该指令会把导致缺页的虚拟地址重发送到地址翻译硬件。但是现在,VP 3 已经缓存在主存中了,那么页命中也能由地址翻译硬件正常处理了。下面是处理缺页后。

(5) 分配页面
下面展示了当操作系统分配一个新的虚拟内存页时对我们示例页表的影响,例如,调用 malloc 的结果。在这个示例中,VP5 的分配过程是在虚拟内存上创建空间并更新 PTE 5,使它指向磁盘上这个新创建的页面。

(6)局部性再次搭救
尽管在整个运行过程中程序引用的不同页面的总数可能超出物理存储器总的大小,但是局部性原则保证了在任意时刻,程序往往在一个较小的活动页面(active page)集合上工作,这个集合叫做工作集(working set)或者常驻集(resident set)。
如果工作集的大小超出了物理存储器的大小,那么程序将产生一种不幸的状态,叫做颠簸(thrashing),这时页面将不断的换进换出。
Comments NOTHING