虚拟内存的定义
虚拟内存是操作系统实现的内存管理的一种技术。它使得应用程序认为它拥有连续的可用的内存(一个连续完整的地址空间),而实际上,它通常是被分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换。
虚拟内存解决的问题
如果不使用虚拟内存,每一个应用程序都直接操作物理内存,如果内存不够用,越界,则会导致程序崩溃。另外,如果 A 程序使用了 1G 的连续空间, B 程序使用了 2G 的空间,内存只有 4G,如果 A 程序终止了,虽然程序释放了内存,假如现在 C 程序要用 2G 的空间,虽然内存有 2G 可用,但是由于不是连续的,被 B 程序分割了,所以 C 程序也无法正常使用。另外,如果两个程序都可以访问真实的物理地址,那都可以修改和读取任意地址内容,这样就会存在很大的安全隐患。所以虚拟内存解决了这三个问题:
- 解决物理内存不足的问题
- 解决物理内存地址空间不连续的问题
- 安全性问题
虚拟内存的简单实现原理
下面我用简单的例子来演示下虚拟内存的实现原理。
假如 CPU 的取址宽度是 0 到 9999,也就是能取 10000 个地址。物理内存也有 10000 个地址。此刻运行着 A 程序,那么操作系统会切换到 A 程序的虚拟地址。虚拟地址和物理地址需要有一个映射关系,这个表肯定要小,毕竟这个表也是存在于内存中的。我们将 10000 个地址以 10 个地址为一块,分成 1000 块。于是这张映射表就有 1000 行。程序和 CPU 操作地址还是以 10000 个地址为单位,取地址时候会通过 MMU 来完成,假如 CPU 要将 9999 号地址存一个内容,这个 9999 是虚拟地址,于是经过转换,9999 / 10 = 999,于是去映射表中的第 999 行,MMU 负责从真实的物理地址中找到一个可用的空间,然后保存到 999 行,假如是存的 1 号物理地址,于是表格中 999 行就对应 1 号物理地址。要将 9999 号虚拟地址内存存一个内容,那 9999 % 10 = 9,于是在 1 号的物理地址中偏移 9 个地址,存入内容,最终保存的位置是 19 号物理地址。
这样一个完整的映射就完成了,程序或者 CPU 不需要关心物理内存,这是操作系统在背后完成的。当然取地址也是这样操作,通过映射的转换和偏移量,找到最终的物理地址。
当然这个一级缓存是真实实现的缩影,原理是相同的,实际的实现有多级缓存来节省更多的内存。而且 CPU 自己也有缓存。