前言
在系统中,程序可以被分为一份一份的,(也即是下文即将提到的页面)计算机运行进程也是可以一份一份地运行。因此我们假设有一个比物理内存更大的虚拟内存来存放当前运行的进程。虚拟内存中存放进程的全部,当计算机需要到进程的某一份时就把它从虚拟内存复制后调入物理内存。如下图示:
上图是一个进程的三个时刻,左边是虚拟内存,右边是物理内存。就物理内存而言,它没有办法同时装入整个的进程。但因为计算机可以一份一份地运行一个进程,所以并不需要整个进程都在物理内存中。
一、虚拟内存的重要性
1.CPU操作的数据一般来自于寄存器或者内存,磁盘上的数据是不能直接操控的。而对于内存而言,存放的数据五花八门,形如“HelloWorld.c”的一段程序,除了运行时,他在不在内存对于计算机运行而言没什么所谓。但是形如操作系统尤其是操作系统内核,他必须常驻内存,而且我们需要对他所在的内存加以保护,否则随便一个程序就能修改它所在的内存,对于系统而言非常不安全。
因此我们不能把物理地址直接暴露给程序,而是利用虚拟地址(稍后说明)
2.程序大于内存的状况经常发生,我们需要一种技术能使得在程序大于内存的情况仍能运行该程序。显然此时又是需要到虚拟内存了。使用虚拟内存的计算机,将程序分为固定大小的页。当执行它时,不需要将所有的页都放进内存中,只需要放进当前执行的代码所在的页。
二、虚拟内存
1.存在形式
虚拟内存是存在磁盘中的连续的 字节大小的单元组成的一个数组。
2.分页
上述提到的虚拟内存是存在于磁盘中的,虚拟内存会被切分为大小一致的页形式,即虚拟页面(Virtual Page,VP)。同样的,物理内存也被分为大小一致的页形式,称为物理页(Physical Page,PP)虚拟页面和物理页面的大小是相同的,所以我们才可以将虚拟页面映射为物理页面。如下图所示:
3.页表
我们已经知道了进程是存在于虚拟内存中的,然后将其一页一页地映射到物理内存上。那么计算机怎么知道哪一页的虚拟页面映射哪一页的物理页呢?那就是利用页表。
上图是一个页表的基本形式(实际上有更多的位提供更多的功能,这里不赘述)他有一个有效位和n位地址字段构成物理内存的区域组成。每一行可视为一个页表项,将虚拟地址翻译为物理地址需要用到一个页表项。为了使cpu可以简单快速的翻译虚拟地址,一般页表存放在一段连续的内存空间中。
页表常驻内存,当cpu访问到有效位为1的页表项时将其送到cpu内部,经翻译得到物理地址。如果访问到有效位为0的情况,会引起一个缺页中断。
4.虚拟内存到物理内存的映射过程
此时先记住一个电子器件内存管理单元(MMU,Memory Managament Unit),他是负责地址翻译的器件。在CPU中。
地址翻译的大致流程如下: