Virtual Memory

Jun 26, 2016


1. 虚拟内存技术

内存相比缓存虽然容量很大,但是仍然有塞满的情况,在这种情况下,计算机会把暂时不用的数据放到硬盘中,这时所使用的硬盘空间称为虚拟内存。

2. 虚拟地址

编译器会决定程序执行时所占用的具体地址,然而程序使用的实际地址只有在被执行时才能确定,否则如果两个程序使用了同一个地址,会引起冲突,而这时非常容易发生的。

为了解决这个矛盾,编译器决定地址时可以假定计算机中不存在其他程序,编译器决定的地址称为虚拟地址。

硬件和操作系统会将虚拟地址映射为程序实际拥有的内存中,这种技术称为地址翻译。

比较朴素的地址翻译方法是将内存分为不定长的段,每个程序分配一个固定的段。

这个方法有一个很明显的缺陷,会产生无法利用的内存碎片使得内存利用率越来越低

3. 分页化地址翻译

为了解决分段方法的内存碎片问题,我们不再使用不定长的内存单位。相反,我们将内存划分为定长的内存块,这种内存块称为页。

一个程序会与多个内存页关联。

对于C++程序而言,编译器会为其分配一个静态数据区,一个栈区,为了栈的增长,两者相距较远。这当中空白的区域可能会产生内存浪费。

分页地址翻译技术解决了这个问题,因为只有正在被使用的地址空间的页才会映射到实际的物理地址中,而当前未使用但未来可能会使用的虚拟地址的页则不会映射到物理地址的页。

这种没有产生映射关系的页被称为虚拟页,因为并不存在实际物理内存中,不会产生浪费。

当程序访问一个虚拟页时,硬件会抛出一个名为缺页中断的异常,操作系统会负责为该虚拟页构建映射关系。

4. 页面调度

对于占用了大量内存的程序来说,其可能会有大量的页长时间不会被访问,这种页称为空闲页。

显然空闲页是一种对资源的浪费。

虚拟内存系统会将空闲页的内容存在磁盘上,并删除映射关系,这个操作称为页面调度

当程序试图访问那个页时,因为没有映射关系,此时会抛出缺页中断,操作系统会从磁盘中将将该页的内容装进内存的一个新页中,并添加新的映射。

一般情况下磁盘比内存慢10W倍,而内存比缓存慢15倍。

一个缺页中断引起的性能问题要比缓存miss严重很多。

然而由于内存要比缓存容量大的多,因而页面调度的次数要少得多。

5. 页面大小

通常,页面大小与系统单独读写一次磁盘所能传输的数据量相等,这是因为读写一次的代价太大,所以希望单次尽可能传输更多的数据。

但是单个页面如果过大,会导致页面内部的碎片。而且页面越大,将要被使用的可能性也越大,意味着会引起更多的缺页中断

一般的页面大小为1KB,4KB,8KB等

6. 工作集合与系统颠簸

一个程序的工作集合就是当前程序正在使用的活跃的内存页面的集合。

在任何时刻,一个程序的工作集合都会远少于其占用的总内存。

一个程序如果缺页中断率高,说明其工作集合正在增加

一个程序如果缺页中断率低,说明其工作集合正在减少

如果所有程序的工作集合都能装入内存,那么所有程序都会较快速的运行

但如果所有程序的工作集合比内存稍微大了一点,比如说,需要一个额外的页

此时,系统不得不废弃一个仍然很活跃的页,如果该页之后仍可能被访问,则系统会将其存入磁盘(称为交换文件),这种页称为脏页。而脏页很快在下一次访问时又会出现另一个脏页。循环往复,性能的灾难。这种情况称为系统颠簸

在选择被替换的页时,通常哪个程序发生缺页中断,会从其自身的页中选择一个淘汰。避免单个程序的抖动影响到其他程序。