缺页中断

缺页中断(英语:Page fault,又名硬错误、硬中断、分页错误、寻页缺失、缺页中断、页故障等)指的是当软件试图访问已映射在虚拟地址空间中,但是目前并未被加载在物理内存中的一个分页时,由中央处理器的内存管理单元所发出的中断。通常情况下,用于处理此中断的程序是操作系统的一部分。

如果操作系统判断此次访问是有效的,那么操作系统会尝试将相关的分页从硬盘上的虚拟内存文件中调入内存。而如果访问是不被允许的,那么操作系统通常会结束相关的进程。

虽然其名为 “页缺失” 错误,但实际上这并不一定是一种错误。而且这一机制对于利用虚拟内存来增加程序可用内存空间的操作系统(比如 Microsoft Windows 和各种类 Unix 系统)中都是常见且有必要的。

微软在较新版 Windows 的资源监视器中使用 “硬错误”(Windows Vista 及以上)、“硬中断”(Windows 8 及以上)这一术语来指代 “页缺失”。

分类

软性

软性页缺失指页缺失发生时,相关的页已经被加载进内存,但是没有向MMU注册的情况。操作系统只需要在MMU中注册相关页对应的物理地址即可。发生这种情况的可能性之一,是一块物理内存被两个或多个程序共享,操作系统已经为其中的一个装载并注册了相应的页,但是没有为另一个程序注册。

可能性之二,是该页已被从 CPU 的工作集中移除,但是尚未被交换到磁盘上。比如 OpenVMS 这样的使用次级页缓存的系统,就有可能会在工作集过大的情况下,将某页从工作集中去除,但是不写入硬盘也不擦除(比如说这一页被读出硬盘后没被修改过),只是放入空闲页表。除非有其他程序需要,导致这一页被分配出去了,不然这一页的内容不会被修改。当原程序再次需要该页内的数据时,如果这一页确实没有被分配出去,那么系统只需要重新为该页在MMU内注册映射即可。

硬性

与软性页缺失相反,硬性页缺失是指相关的页在页缺失发生时未被加载进内存的情况。这时操作系统需要:

  1. 寻找到一个空闲的页。或者把另外一个使用中的页写到磁盘上(如果其在最后一次写入后发生了变化的话),并注销在 MMU 内的记录。

  2. 将数据读入被选定的页。

  3. 向 MMU 注册该页。

硬性页缺失导致的性能损失是很大的。以一块 7200rpm 的主流机械硬盘为例,其平均寻道时间为 8.5 毫秒,读入内存需要 0.05 毫秒。相对的,DDR3 内存的访问延迟通常在数十到 100 纳秒之间,性能差距可能会达到 8 万到 22 万倍。

另外,有些操作系统会将程序的一部分延迟到需要使用的时候再加载入内存执行,以此来提升性能。这一特性也是通过捕获硬性页缺失达到的。当硬性页缺失过于频繁的发生时,称发生系统颠簸。

无效

当程序访问的虚拟地址是不存在于虚拟地址空间内的时候,则发生无效页缺失。一般来说这是个软件问题,但是也不排除硬件可能,比如因为内存故障而损坏了一个正确的指针。

具体动作与所使用的操作系统有关,比如 Windows 会使用异常机制向程序报告,而类Unix系统则会使用信号机制。如果程序未处理相关问题,那么操作系统会执行默认处理方式,通常是转储内存、终止相关的程序,然后向用户报告。

中断

是指计算机在执行程序的过程中,当出现异常情况或特殊请求时,计算机停止现行程序的运行,转向对这些异常情况或特殊请求的处理,处理结束后再返回现行程序的间断处,继续执行原程序。

缺页中断的次数

中断次数=进程的物理块数×页面置换次数。

缺页中断的顺序

缺页中断发生时的事件顺序如下:

  1. 硬件陷入内核,在内核堆栈中保存程序计数器。大多数机器将当前指令的各种状态信息保存在特殊的 CPU 寄存器中。

  2. 启动一个汇编代码例程保存通用寄存器和其他易失的信息,以免被操作系统破坏。这个例程将操作系统作为一个函数来调用。

  3. 当操作系统发现一个缺页中断时,尝试发现需要哪个虚拟页面。通常一个硬件寄存器包含了这一信息,如果没有的话,操作系统必须检索程序计数器,取出这条指令,用软件分析这条指令,看看它在缺页中断时正在做什么。

  4. 一旦知道了发生缺页中断的虚拟地址,操作系统检查这个地址是否有效,并检查存取与保护是否一致。如果不一致,向进程发出一个信号或杀掉该进程。如果地址有效且没有保护错误发生,系统则检查是否有空闲页框。如果没有空闲页框,执行页面置换算法寻找一个页面来淘汰。

  5. 如果选择的页框 “脏” 了,安排该页写回磁盘,并发生一次上下文切换,挂起产生缺页中断的进程,让其他进程运行直至磁盘传输结束。无论如何,该页框被标记为忙,以免因为其他原因而被其他进程占用。

  6. 一旦页框 “干净” 后(无论是立刻还是在写回磁盘后),操作系统查找所需页面在磁盘上的地址,通过磁盘操作将其装入。该页面被装入后,产生缺页中断的进程仍然被挂起,并且如果有其他可运行的用户进程,则选择另一个用户进程运行。

  7. 当磁盘中断发生时,表明该页已经被装入,页表已经更新可以反映它的位置,页框也被标记为正常状态。

  8. 恢复发生缺页中断指令以前的状态,程序计数器重新指向这条指令。

  9. 调度引发缺页中断的进程,操作系统返回调用它的汇编语言例程。

  10. 该例程恢复寄存器和其他状态信息。

缺页中断处理过程

在请求分页系统中,可以通过查询页表中的状态位来确定所要访问的页面是否存在于内存中。每当所要访问的页面不在内存时,会产生一次缺页中断,此时操作系统会根据页表中的外存地址在外存中找到所缺的一页,将其调入内存。

缺页本身是一种中断,与一般的中断一样,需要经过 4 个处理步骤:

  1. 保护 CPU 现场

  2. 分析中断原因

  3. 转入缺页中断处理程序进行处理

  4. 恢复 CPU 现场,继续执行

但是缺页中断时由于所要访问的页面不存在与内存时,有硬件所产生的一种特殊的中断,因此,与一般的中断存在区别:

  1. 在指令执行期间产生和处理缺页中断信号

  2. 一条指令在执行期间,可能产生多次缺页中断

  3. 缺页中断返回时,执行产生中断的那一条指令,而一般的中断返回时,执行下一条指令