是什么

  • 定义虚存跨页计算指确定一段连续数据(如数组)在虚拟地址空间中所覆盖的不同虚拟页面的集合;缺页异常次数是指访问该数据过程中,由于目标页面未调入主存而触发操作系统缺页中断处理的累计次数。

  • 大白话:算跨几页就是看数据从头到尾占用的地址区间切穿了几个 4KB(或其它页大小)的格子;算缺页几次就是看程序在顺序跑的过程中,踩进了几个原本不在内存里的全新格子里

核心内容

1. 数组地址区间的标准求解

设数组首地址为 ,数组元素个数为 ,单个元素大小为

  • 数据总字节数

  • 起始字节地址

  • 末尾字节地址(必须减 1 字节)

2. 判定跨越页数的通用步骤

设页面大小为 (如 ),页内偏移占 位(4KB 对应 位):

  1. 求起始页号

  2. 求末尾页号

  3. 计算跨越的总页数

3. 缺页次数判定法则

  • 前提条件

    • 若题目明确声明“执行前数据不在主存中,且执行期间不发生页面置换”;

    • 数组为顺序/线性访问遍历。

  • 计算规则

    • 程序首次进入每一个新页面时,必然发生 1 次冷缺页(Compulsory Page Fault)

    • 只要页面进入主存后不再被置换出,后续对同页面内其余元素的访问全部命中,不再缺页

    • 核心结论:==缺页异常次数 = 顺序访问所覆盖的不同页面总数==。

例题

  • 题目(2025 统考 408 真题节选):

    页面大小为 4KB,数组定义为 int d[2048];sizeof(int) = 4)。数组 的起始虚拟地址为 0180 0020H。若执行循环遍历前数组 未调入主存,且遍历过程中不发生页面置换,求:

    1. 数组 分布在几个页中?

    2. 访问数组 所引起的缺页次数是多少?

  • 分析

    • 页面大小:,即虚拟地址的低 12 位(后 3 位十六进制)为页内偏移,高 20 位(前 5 位十六进制)为虚页号。

    • 数组总大小:(恰好等于 2 个整页的大小)。

    • 起始字节地址:0180 0020H

    • 末尾字节地址:

    • 起始虚页号:取 0180 0020H 的高 20 位 01800H

    • 末尾虚页号:取 0180 201FH 的高 20 位 01802H

  • 答案

    1. 分布页数

      数组占用的虚页号依次为 01800H01801H01802H

    2. 缺页次数

      由于初始不在主存且不发生置换,线性遍历首次访问 d[0](页 01800H)、跨入页 01801H 的首个元素、以及跨入页 01802H 的首个元素时各发生 1 次缺页异常。

⚠️ 易错点

Warning

  • 只拿总字节数除以页大小 误认为 。这是最常见的致命陷阱!只有当首地址严格在页边界对齐(如 ...000H)时才成立;若首地址有偏移(如 ...020H),尾部必然会溢出切入第 3 个页。

  • 末尾地址未减 1 字节 若误算末尾地址为 ,当数组恰好填满某页边界时,会把下一页的第一个字节算进来,导致多算 1 页。

  • 混淆代码缺页与数据缺页 注意题目是否注明“代码已在内存/Cache 中”。若代码不在内存中,取指令本身也会引起缺页;若题目仅问“访问数组引起”,则只需统计数据页。 这里面的“减 1”“加 1”其实分别对应着日常计算中非常经典的“末尾字节边界”“植树/闭区间计数”问题。

1. 算末尾地址时,为什么要「减 1」?(闭区间边界问题)

  • 本质原理:从第 个字节开始数,总共有 个字节,那么最后一个字节的偏移量是

  • 生活中的直观例子

    • 如果你要从第 100 页 开始读 1 页 书,你读的是哪一页?是第 100 页(即 ),而不是

    • 如果读 3 页 书,你读的是 100、101、102 这三页,最后一页是

  • 不减 1 的致命后果

    • 假设页大小是 4KB(1000H),数组首地址是 0000H,数组长度恰好是 4KB(1000H 字节)。

    • 正确的最后一个字节地址是:0000H + 1000H - 1 = 0FFFH(依然在第 0 页)。

    • 如果你不减 1:0000H + 1000H = 1000H。这个 1000H 已经是第 1 页的第 0 个字节了!你会误以为数据跨到了第 1 页,从而错误地多算了一页。

2. 算跨越总页数时,为什么要「加 1」?(两端都包含的闭区间计数)

  • 本质原理:两端都包含的连续整数个数公式为:

  • 生活中的直观例子

    • 如果数据占用了 第 3 页、第 4 页、第 5 页,一共占了几页?

    • 显然是 3 页。但如果直接做减法: 页,就会少算起始的那一页。

    • 正确算法是: 页。

  • 在 408 题目中的应用

    • 起始页号:01800H

    • 末尾页号:01802H

    • 实际包含的页面有:01800H01801H01802H 这 3 个。

一句话速记口诀

  • 算末尾地址「减 1」:防溢出,保证抓到的是数据占用的最后一个字节,不把下一个无辜的字节算进来。

  • 算页面总数「加 1」:闭区间计数,保证头尾两页都算在内