(四)内存那些事儿:内存交换和虚拟内存

内存交换和虚拟内存

引言:从物理限制到虚拟扩展的进化

在早期计算机系统中,程序直接使用物理内存,面临两个根本性限制:

  1. 容量限制:程序大小不能超过物理内存容量
  2. 并发限制:多个程序的内存需求总和不能超过物理内存

随着软件复杂度增长和多任务需求增加,这些限制成为系统发展的瓶颈。为突破物理内存的限制,计算机科学家开发出了两个关键技术:

  • 内存交换:通过进程级的换入换出机制扩展可用内存
  • 虚拟内存:通过页面级的虚拟化技术创造”无限”内存的假象

这两种技术代表了内存管理发展的不同阶段和思路,共同构成了现代内存管理的基础。

技术发展的层次关系

物理内存限制
    ↓
内存交换(进程级扩展)
    ↓
虚拟内存(页面级虚拟化)
    ↓
现代统一内存管理体系

核心知识点体系

1. 内存交换:突破并发限制的第一步

1.1 技术背景与设计动机

历史问题:早期多任务系统中,所有进程必须同时常驻内存,导致:

  • 系统可运行的进程数量受限
  • 大部分时间进程处于等待状态,内存利用率低
  • 无法运行内存需求超过可用空间的进程组合

解决思路:既然进程经常处于等待状态,为什么不将等待的进程临时移出内存?

1.2 内存交换的核心机制

基本概念

  • 交换区:磁盘上专门用于存储被换出进程的区域
  • 换出(Swap Out):将进程从内存转移到交换区
  • 换入(Swap In):将进程从交换区重新载入内存

交换过程

内存紧张 → 选择换出进程 → 保存完整进程映像 → 释放内存空间
    ↓
进程需要运行 → 查找交换区 → 重新载入内存 → 恢复执行

1.3 换出策略的设计考量

换出优先级(从高到低):

  1. 阻塞状态进程:正在等待I/O或其他事件,短期内不需要CPU
  2. 低优先级进程:对系统响应性影响较小
  3. 内存占用大的进程:换出后释放更多空间
  4. 长时间未活跃进程:根据历史访问模式判断

状态转换图

就绪 ←→ 运行 ←→ 阻塞
 ↓        ↓       ↓
就绪挂起 ←→ (无) ←→ 阻塞挂起

1.4 内存交换的局限性

  • 粒度粗糙:以整个进程为单位,无法精细管理
  • 开销巨大:每次交换涉及大量数据传输
  • 地址重定位:进程重新载入时可能分配到不同物理地址
  • 碎片问题:仍然存在外部碎片,内存利用率有限

关键认识:内存交换解决了并发数量问题,但没有解决单个程序大小超过物理内存的问题。


2. 虚拟内存:内存管理的革命性突破

2.1 设计思想的根本转变

核心洞察:程序运行时通常只需要访问一小部分代码和数据(局部性原理),没必要将整个程序载入内存。

虚拟化思想

程序视角:拥有完整、连续的地址空间
    ↓
实际情况:只有部分页面在物理内存中
    ↓
访问不存在的页面 → 缺页中断 → 动态载入

2.2 局部性原理:虚拟内存的理论基础

时间局部性

  • 最近访问的内存位置在近期内再次被访问的概率很高
  • 例如:循环变量、热点函数

空间局部性

  • 如果某个内存位置被访问,其邻近位置也很可能被访问
  • 例如:数组遍历、顺序执行的代码

局部性的量化意义

工作集理论:程序在某时间窗口内访问的页面集合
通常情况:程序90%的时间只访问10%的页面

2.3 虚拟内存的实现机制

2.3.1 地址空间虚拟化

虚拟地址空间结构

┌─────────────────────────────────────┐ ← 4GB (32位系统)
│           未使用区域                │
├─────────────────────────────────────┤
│            堆区域                   │ ← 动态增长
├─────────────────────────────────────┤
│         内存映射区域                │ ← 文件映射、动态库
├─────────────────────────────────────┤
│            栈区域                   │ ← 向下增长
├─────────────────────────────────────┤
│           BSS段                     │ ← 未初始化数据
├─────────────────────────────────────┤
│          数据段                     │ ← 已初始化数据
├─────────────────────────────────────┤
│          代码段                     │ ← 程序代码
└─────────────────────────────────────┘ ← 0x0

关键特性

  • 每个进程拥有独立的4GB虚拟地址空间
  • 虚拟地址空间远大于物理内存
  • 不同进程的相同虚拟地址映射到不同物理地址
2.3.2 按需分页机制

请求分页的工作流程

程序启动 → 创建虚拟地址空间 → 建立页表框架
    ↓
访问页面 → 检查页表 → 页面不存在 → 缺页中断
    ↓
操作系统 → 分配物理页框 → 从磁盘载入 → 更新页表
    ↓
重新执行访问指令 → 正常访问 → 继续执行

页表项的状态信息

┌─────────┬─────────┬─────────┬─────────┬─────────┐
│ 存在位  │ 访问位  │ 修改位  │ 权限位  │ 页框号  │
└─────────┴─────────┴─────────┴─────────┴─────────┘
    ↓         ↓         ↓         ↓         ↓
  在内存?   被访问?   被修改?   读/写/执行  物理位置

2.4 页面置换:内存容量的动态管理

置换触发条件

  • 物理内存不足,无法为新页面分配页框
  • 需要载入新页面,但所有页框都被占用

经典置换算法对比

算法 核心思想 实现复杂度 性能表现 适用场景
FIFO 最先进入的页面最先置换 简单 一般 教学演示
LRU 置换最长时间未访问的页面 复杂 最优 理论标准
Clock 循环扫描,置换未访问页面 适中 良好 实际系统
LFU 置换访问频率最低的页面 复杂 良好 特定模式

Clock算法详解

页面环形链表,每个页面有访问位
    ↓
扫描指针循环移动
    ↓
访问位=1:清零并继续;访问位=0:选择置换
    ↓
近似LRU效果,硬件开销小

3. 内存交换与虚拟内存的关系梳理

3.1 技术层次的演进关系

历史发展阶段

单任务系统 → 多任务系统 → 内存交换 → 虚拟内存 → 现代统一管理
     ↓           ↓           ↓           ↓            ↓
 直接访问    竞争内存     进程换出     页面管理     混合策略

3.2 概念对比与联系

维度 内存交换 虚拟内存
管理粒度 进程级 页面级
主要目的 增加并发进程数 突破程序大小限制
工作机制 整体换入换出 按需页面载入
地址转换 重定位寄存器 页表映射
存储开销 交换区存储 页表存储
硬件依赖 基础重定位 MMU支持

3.3 现代系统中的融合

统一的内存管理架构

进程级管理 ←→ 页面级管理
     ↓             ↓
内存交换策略    虚拟内存机制
     ↓             ↓
    共同支撑现代操作系统

融合特点

  • 分层管理:进程级调度 + 页面级管理
  • 策略协同:换出进程的所有页面 vs 选择性页面置换
  • 性能优化:根据系统负载动态选择策略

4. 关键问题与解决方案

4.1 颠簸现象:虚拟内存的性能陷阱

颠簸的产生机制

内存不足 → 频繁缺页 → 大量页面置换 → CPU利用率下降
    ↓
OS误以为需要更多进程 → 增加多道程序度 → 加剧内存竞争
    ↓
进入恶性循环:更多缺页 → 更多置换 → 系统几乎停滞

工作集理论的解决方案

  • 工作集:进程在时间窗口Δ内访问的页面集合
  • 驻留集:进程当前在内存中的页面集合
  • 平衡条件:驻留集 ≥ 工作集,避免频繁缺页

颠簸的预防策略

  1. 工作集算法:为每个进程维护足够的驻留集
  2. 页面故障频率算法:监控缺页率,动态调整驻留集大小
  3. 负载控制:当检测到颠簸时,挂起部分进程

4.2 地址转换的性能优化

TLB(Translation Lookaside Buffer)

虚拟地址 → 查TLB缓存 → 命中:直接获得物理地址
            ↓ 未命中
         查页表 → 更新TLB → 获得物理地址

多级页表的空间优化

单级页表:4MB空间(32位系统)
    ↓
二级页表:大多数二级页表可以不存在
    ↓
实际空间:通常小于100KB

5. 现代应用与发展趋势

5.1 现代操作系统的实现策略

Linux内存管理

  • slab分配器:内核对象的高效管理
  • 伙伴系统:页框的分配与合并
  • OOM killer:内存耗尽时的进程选择机制
  • memory cgroup:容器化环境的内存隔离

Windows内存管理

  • 页面缓冲池:系统页面的统一管理
  • 工作集管理:进程内存的动态调整
  • 内存压缩:减少页面置换的创新技术

5.2 新技术发展趋势

非易失性内存(NVM)

传统:内存(快速/易失) + 磁盘(慢速/持久)
    ↓
未来:NVM(中速/持久) + DRAM(快速/易失)
    ↓
影响:重新设计页面置换策略

内存压缩技术

  • 压缩不活跃页面而非置换到磁盘
  • 减少I/O开销,提高响应速度
  • zRAM、zswap等实现方案

大内存系统优化

  • 大页支持:减少页表项数量,提高TLB效率
  • NUMA优化:考虑内存访问的局部性
  • 热插拔支持:动态调整内存容量

知识点关联网络

1. 技术演进的因果链条

物理限制 → 多任务需求 → 内存竞争 → 交换机制
    ↓          ↓           ↓          ↓
程序大小限制 → 局部性发现 → 虚拟内存 → 现代管理

2. 核心概念的支撑关系

  • 局部性原理虚拟内存 的理论基础
  • 页表机制 支撑 地址虚拟化内存保护
  • 缺页中断 连接 硬件检测软件管理
  • 置换算法 基于 访问模式 实现 内存优化
  • 工作集理论 指导 性能调优颠簸预防

3. 性能与复杂度的平衡

简单性 ←→ 功能性
内存交换    虚拟内存

开销控制 ←→ 性能提升
直接置换    智能算法

硬件成本 ←→ 软件复杂度
基础支持    完整虚拟化

总结:现代内存管理的核心思想

1. 虚拟化的威力

通过虚拟内存技术,操作系统成功地将物理限制转化为逻辑抽象,为程序提供了”无限”内存的假象。

2. 分层管理的智慧

现代系统将内存管理分解为多个层次:

  • 硬件层:MMU提供地址转换支持
  • 内核层:页面分配、置换算法、缺页处理
  • 应用层:堆管理器、垃圾回收器

3. 性能优化的艺术

通过局部性原理的应用和各种缓存机制(TLB、页面缓存),系统在提供强大功能的同时保持了良好的性能。

4. 未来发展的方向

  • 硬件软件协同:利用新型存储器特性优化管理策略
  • 智能化管理:基于机器学习的预测和优化
  • 容器化支持:适应云计算和容器化的新需求

内存交换与虚拟内存技术的发展历程体现了计算机科学解决复杂问题的典型思路:从简单的物理映射到复杂的虚拟化抽象,从粗粒度的进程管理到细粒度的页面控制,这种分层抽象和逐步优化的方法论对理解其他系统技术具有重要的指导意义。




    Enjoy Reading This Article?

    Here are some more articles you might like to read next:

  • (七)内核那些事儿:操作系统对网络包的处理
  • (六)内核那些事儿:文件系统
  • (五)内核那些事儿:系统和程序的交互
  • (四)内核那些事儿:设备管理与驱动开发
  • (三)内核那些事儿:CPU中断和信号