std::queue 单独无法实现正确 FIFO 页面置换,因其不维护驻留状态,查页是否在内存需 O(m) 遍历,且淘汰后未清理标记导致重复缺页;必须搭配 std::unordered_set 同步更新。

仅用 std::queue 实现 FIFO 页面置换,命中率一定算错——它不维护驻留状态,查“页是否已在内存”退化为 O(m) 遍历,且淘汰后残留脏数据,导致重复缺页、命中虚低。
为什么 std::queue 单独用不了 FIFO
核心动作有三步:① 判断页是否驻留;② 缺页时决定是否淘汰;③ 淘汰后同步清理驻留标记。std::queue 只做②,不做①和③。
-
std::queue::find()根本不存在,编译失败;若改用遍历判断,m=64时单次访问就要比 64 次 - 没配
std::unordered_set→ 同一页连续访问(如0 0 0)第二次起全判缺页 - 淘汰页后只
queue.pop(),没in_memory.erase(victim)→ 该页后续再访仍触发缺页,集合里存着“幽灵页号”
std::queue 必须搭配 std::unordered_set 同步更新
二者职责分明:queue 管谁最老,unordered_set 管谁还在内存。所有增删必须原子对齐,一步都不能漏。
- 装入新页时:
pageQueue.push(page)✅ +inMemory.insert(page)✅ - 淘汰旧页时:
int victim = pageQueue.front(); pageQueue.pop();✅ +inMemory.erase(victim)✅ - 命中判断只查集合:
if (inMemory.find(page) != inMemory.end()),O(1),不碰队列 - 初始化两个结构都为空;不要预填页号,真实调度从空内存开始
手写循环数组时 cur 指针的边界陷阱
用 std::vector + int cur = 0 模拟 FIFO,性能好但极易越界或逻辑漂移。
-
cur是“下次该覆盖的位置”,不是“当前最老页索引”——最老页永远在frames[cur] - 只在“缺页且
frames.size() == frameCount”时才执行cur = (cur + 1) % frameCount - 数组大小必须严格等于
frameCount,多一分可能覆盖相邻变量,少一分会导致下标越界 - 即使内存未满,新页也必须加入
inMemory.insert(page);只是此时不更新cur、不淘汰
命中率分母必须是总访问次数,一个都不能少
缺页率 = 缺页次数 / 总页面访问次数。这个“总次数”就是输入序列长度 n,不是装入次数、不是去重后长度、更不是“填满内存后的访问数”。
- 示例序列
7 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1共 17 次访问 → 分母固定为 17 - 第 1 次访问
7:内存空,缺页,计入分子;第 5 次再访0:命中,不加分子但计入分母 - 若跳过前
frameCount次(填空阶段)不计分母 → 命中率人为抬高,与真实 OS 行为脱节 - FIFO 的“先进”指进入内存的时间戳,不是访问序列位置;交叉访问(如
0 1 2 0 1 3)下,仅靠队列头尾无法体现谁更老——必须靠同步更新保证逻辑一致性
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











