文章中如果有图看不到,可以点这里去 csdn 看看。从那边导过来的,文章太多,没法一篇篇修改好。

内存分页的实现,换页、页缓存相关内容介绍

本文来详细深入地探讨一下内存分页的实现,包括换页(页面置换)和页缓存(Page Cache)的相关内容。这是一个操作系统内存管理的核心机制。


第一部分:内存分页(Paging)的基本原理

1. 为什么需要内存分页?

在早期的操作系统或简单系统中,采用连续内存分配方式(如分段)。这种方式容易产生外部碎片,导致内存利用率低下,尽管可以通过紧凑技术解决,但代价很高。

内存分页的核心思想是:将物理内存和虚拟内存都划分为固定大小的块,从而避免外部碎片,提高内存管理灵活性和利用率。

2. 核心概念
  • 页(Page): 进程虚拟地址空间中的固定大小块。
  • 帧(Frame): 物理内存中的固定大小块。页和帧的大小必须相同,通常为 4KB(现代系统也支持 2MB、1GB 等大页)。
  • 页表(Page Table): 每个进程独有的数据结构,用于存储虚拟页到物理帧的映射关系。
  • 内存管理单元(MMU): CPU中的一个硬件单元,负责在进程访问内存时,通过查询页表,将虚拟地址转换为物理地址。
3. 地址转换过程

假设虚拟地址为 32 位,页大小为 4KB(12位偏移量)。

  1. CPU发出一个虚拟地址。
  2. MMU将虚拟地址拆解为两部分:
    • 虚拟页号(VPN, Virtual Page Number): 高 20 位。用于索引页表。
    • 页内偏移(Offset): 低 12 位。找到物理帧后,直接加上此偏移得到最终物理地址。
  3. MMU以 VPN 为索引,查找当前进程的页表,找到对应的页表项(PTE, Page Table Entry)
  4. PTE中包含了目标物理帧号(PFN, Physical Frame Number),以及一些控制位(如存在位、读写权限位等)。
  5. MMU将 PFN 和原始的 Offset 组合,得到最终的物理地址,并访问该地址。
4. 页表项(PTE)的构成

一个典型的 PTE 包含以下信息(具体结构因架构而异):

位域含义
存在位(Present Bit)核心位。1 表示该页已在物理内存中;0 表示不在内存中(在磁盘上),访问它会触发缺页异常
物理帧号(PFN)该虚拟页对应的物理内存帧号。
读写位(Read/Write)1 表示可写;0 表示只读。
用户/超级用户位(User/Supervisor)决定用户态程序是否可以访问该页。
访问位(Accessed Bit)当该页被读或写时,硬件自动置 1。用于页面置换算法(如LRU的近似)。
脏位(Dirty Bit)当该页被时,硬件自动置 1。表示该页已被修改,换出时需要写回磁盘。
缓存禁用位(Cache Disable)用于特殊目的(如内存映射I/O),禁止缓存该页。
其他架构相关标志位

第二部分:换页(Paging)/页面置换(Page Replacement)

1. 为什么需要换页?

物理内存是有限的。通过分页,操作系统创造了虚拟内存的抽象,让每个进程都认为自己拥有巨大的、连续的内存空间。实际上,一个进程的所有页并不需要同时驻留在物理内存中。

  • 当进程访问一个存在位为 0 的页面时,CPU会触发一个缺页异常(Page Fault)
  • 操作系统捕获这个异常,并执行缺页异常处理程序
2. 缺页异常处理流程
  1. 陷阱处理: CPU陷入内核态,保存现场,将控制权交给OS的异常处理程序。
  2. 检查有效性: OS检查请求的虚拟地址是否合法(在进程地址空间内且有访问权限)。如果无效,终止进程(Segment Fault)。
  3. 寻找空闲帧: 如果地址有效,OS需要找到一个空闲的物理帧来存放即将被换入的页。
  4. 页面置换(如果需要): 如果当时没有空闲的物理帧,OS必须换出一个当前已在内存中的页,为新的页腾出空间。
  5. 读入页面: OS调度一个磁盘I/O操作,将所需页面从交换空间(Swap Space)(对于匿名内存)或磁盘文件(对于内存映射文件)中读入到第3步准备好的物理帧中。
  6. 更新页表: 当I/O完成後,OS更新页表项,将存在位置 1,并写入物理帧号(PFN)。
  7. 恢复执行: OS恢复异常发生时的现场,重新执行那条引发缺页异常的指令。这次,MMU就能成功完成地址转换了。
3. 页面置换算法(Page Replacement Algorithms)

当没有空闲帧时,选择换出哪个页至关重要。糟糕的选择会导致刚换出的页很快又被访问,需要换入,这种高频度的换页行为称为抖动(Thrashing)。目标是尽可能减少缺页率

  1. 最佳置换(OPT, Optimal)

    • 思想: 换出在未来最长时间内不会被访问的页。这是一种理想算法,无法实现,但可作为衡量其他算法优劣的基准。
  2. 先进先出(FIFO)

    • 思想: 维护一个队列,换出在内存中驻留时间最长的页。
    • 问题: 可能会换出经常被访问的“老”页(Belady异常:分配的物理帧增多,缺页率反而上升)。
  3. 最近最少使用(LRU, Least Recently Used)

    • 思想: 换出最长时间没有被访问的页。这符合局部性原理(最近被访问的页,很可能在不久的将来再次被访问)。
    • 实现挑战: 需要精确记录每个页的访问时间戳,每次内存访问都需要更新,硬件开销巨大
    • 近似LRU算法: 实际系统中广泛使用。
      • 时钟算法(Clock/Second Chance): 将页表项组织成一个环形链表,有一个“指针”循环移动。检查指向的页:如果其访问位是 1,则置 0 并跳过;如果是 0,则选择换出它。给了每个页“第二次机会”。
      • 改进型时钟算法: 同时考虑访问位(A)和脏位(D)。优先换出 (A=0, D=0) 的页,因为不需要写回磁盘,开销最小。
  4. 最不经常使用(LFU, Least Frequently Used)

    • 思想: 换出访问频率最低的页。需要为每个页维护一个计数器。

第三部分:页缓存(Page Cache)

1. 什么是页缓存?

页缓存是操作系统内核使用物理内存的一部分来缓存磁盘数据的机制。它的单位就是内存页(Page)。几乎所有对磁盘文件的读写都会通过页缓存进行。

2. 为什么需要页缓存?

磁盘I/O速度比内存访问慢几个数量级。页缓存的存在是为了:

  • 减少磁盘I/O次数: 多次对文件同一部分的读写会在内存中进行,无需每次都访问慢速磁盘。
  • 提升系统响应速度: 利用局部性原理,预读数据到缓存,使得后续读取速度极快。
  • 统一缓存: 无论是应用程序的内存映射文件(mmap)还是传统的read/write系统调用,最终都使用同一份页缓存,避免了重复缓存,提高了内存利用率。
3. 页缓存的工作机制
  • 读操作

    1. 应用程序发起read系统调用。
    2. 内核检查请求的文件数据块是否已在页缓存中。
    3. 缓存命中(Cache Hit): 数据在缓存中,直接从内存拷贝到用户缓冲区,过程极快。
    4. 缓存未命中(Cache Miss): 数据不在缓存中,内核分配一个页帧,发起磁盘I/O,将数据从磁盘读入页缓存,然后再拷贝到用户缓冲区。
  • 写操作

    1. 应用程序发起write系统调用。
    2. 数据被拷贝到页缓存中对应的页面(写回缓存,Write Back)。
    3. 此时,页被标记为脏页(Dirty Page)
    4. 内核不会立即将数据写回磁盘,而是由后台线程(如pdflush)在适当的时候(如脏页太多、缓存回收、定时同步)异步地将脏页写回磁盘。
    5. 这种策略称为延迟写(Write Behind),它可以将多次小写操作合并为一次大的磁盘写入,极大提升I/O性能。
  • 内存映射文件(mmap)

    • mmap是一种特殊的文件访问方式。它将一个文件直接映射到进程的虚拟地址空间。
    • 进程对这段内存的读写,实际上直接操作的就是页缓存中的页面。
    • 这避免了read/write系统调用中的内核态与用户态之间的数据拷贝,非常高效。
4. 页缓存与换页的交互

页缓存和换页机制紧密合作,共同管理物理内存:

  1. 内存回收: 当系统物理内存紧张时(例如,应用程序申请内存而空闲内存不足),内核的内存回收机制会开始工作。
  2. 回收目标: 回收的目标包括两部分:
    • 匿名页(Anonymous Pages): 如堆、栈等没有文件背景的页。这些页只能被换出到交换分区(Swap)
    • 页缓存(File-backed Pages): 有文件背景的页。因为原始数据在磁盘上,直接丢弃即可(如果是脏页,则需要先写回磁盘再丢弃)。
  3. 回收策略: Linux等现代操作系统通常优先回收页缓存,因为其回收开销(可能只需丢弃)通常小于交换匿名页(必须写入交换区)。这可以通过/proc/sys/vm/swappiness参数来调节倾向性。

总结

概念角色与目的关键点
内存分页基础机制: 提供虚拟内存抽象,高效管理物理内存,避免外部碎片。页表、MMU、地址转换、缺页异常。
换页扩容机制: 当物理内存不足时,通过将暂不使用的页换出到磁盘,为急需的页腾出空间,实现内存的“超售”。缺页处理、页面置换算法(LRU、Clock)、抖动。
页缓存加速机制: 利用物理内存缓存磁盘数据,将慢速磁盘访问转换为快速内存访问,提升I/O性能。缓存命中/未命中、延迟写、脏页、与mmap的关系。

这三者共同构成了现代操作系统高效、灵活的内存管理系统,使得应用程序可以运行在比物理内存大得多的虚拟地址空间上,同时享受到接近内存速度的I/O性能。

posted @ 2025-08-27 12:55  NeoLshu  阅读(12)  评论(0)    收藏  举报  来源