六:操作系统虚拟内存之抖动
内存管理难题:理解抖动 (Thrashing) 与工作集模型
在现代操作系统中,虚拟内存极大地扩展了我们对内存容量的感知,并允许多个进程同时运行。然而,这种抽象并非没有代价。当物理内存资源紧张,而系统试图支持过多的活跃进程时,可能会陷入一种效率极低的状态——抖动 (Thrashing)。
理解抖动的原因以及如何避免它是构建高效系统的关键。本文将深入探讨抖动是什么、为什么会发生,以及操作系统如何利用工作集模型 (Working Set Model) 等概念来管理内存以防止或缓解抖动。
1. 什么是抖动 (Thrashing)?
抖动是虚拟内存系统中的一种病态现象。它发生在系统过度使用交换空间时,即操作系统花费大部分时间将页从物理内存换出到磁盘,然后再将需要的页从磁盘换入物理内存,而不是执行实际的应用程序指令。
想象一下这样的场景:系统中运行着很多进程,它们都在积极地访问内存。由于物理内存不足,每个进程可能无法获得足够的帧来容纳其当前正在使用的所有页(即其工作集)。当一个进程需要访问一个不在物理内存中的页时,会发生缺页中断 (Page Fault)。为了加载这个新页,操作系统必须找到一个物理帧,如果所有帧都已被占用,它就必须选择一个页牺牲者将其内容写回(如果修改过)到磁盘,然后才能将新页从磁盘加载进来。
在抖动状态下,这个过程会变得非常频繁:
- 进程 P 发生缺页中断。
- 操作系统需要将 P 的一个旧页换出,从磁盘读取新页。
- 进程 P 等待磁盘 I/O 完成。
- 在等待期间,CPU 可能切换到另一个进程 Q。
- 进程 Q 也很快发生缺页中断。
- 操作系统需要将 Q 的一个旧页换出,从磁盘读取新页。
- 进程 Q 等待磁盘 I/O 完成。
- …如此循环…
结果是,CPU 大部分时间都处于空闲状态(等待缓慢的磁盘 I/O),而磁盘却异常繁忙。系统的吞吐量急剧下降,响应时间变得非常长。
抖动的恶性循环:
过度提交内存 → 进程帧数不足 → 高缺页率 → 大量磁盘 I/O (换页) → CPU 利用率下降 (等待 I/O) → 调度器认为 CPU 空闲,尝试运行更多进程 → 更多进程竞争有限帧 → 帧数更少 → 缺页率更高 → 更大量的磁盘 I/O → CPU 利用率进一步下降…
这个循环不断加剧,导致系统几乎无法完成任何有效工作。在抖动状态下,增加更多的进程反而会使情况变得更糟,因为它们会进一步争夺本已稀缺的物理帧。
症状:
- 极高的缺页中断率。
- 极低的 CPU 利用率。
- 磁盘活动指示灯持续闪烁(尤其是在交换分区)。
- 系统响应极其缓慢或完全无响应。
2. 抖动的原因
抖动的根本原因在于系统中所有活跃进程的当前内存需求(总工作集大小)超过了可用的物理内存容量。
具体来说,主要原因包括:
- 进程数量过多: 系统试图同时运行的进程数量超过了物理内存所能合理支持的限度。
- 每个进程分配的帧数过少: 如果为每个进程分配的物理帧不足以容纳其正常执行所需的最小页集合(即工作集),它将不断地发生缺页中断。
- 全局页面替换策略: 如果系统使用全局替换策略(页面替换算法可以从系统中任何进程的帧中选择牺牲页),当一个进程发生缺页时,它可能会替换掉另一个进程的活跃页。这可能导致被替换页所属的进程很快也发生缺页,形成连锁反应。如果系统的总内存需求超过物理内存容量,全局替换只会加速将活跃页逐出内存的过程,从而导致全局性的抖动。
- 程序设计不良: 程序的内存访问模式不具备良好的局部性(例如,随机访问大型数据结构),导致工作集过大或频繁变化,即使有较多内存也难以有效管理。
3. 工作集模型 (Working Set Model)
为了防止抖动,操作系统需要一种方法来判断一个进程当前到底需要多少物理内存,以及系统总体是否过载。工作集模型就是由 Peter Denning 提出的一个重要概念,它尝试为解决这个问题提供理论基础。
工作集的定义:
进程 P 的工作集 W(t, Δ) 是在时间 t 之前的Δ 时间窗口内,进程 P 访问过的所有页的集合。
t
表示当前时间点。Δ
(Delta) 是一个时间间隔参数,通常表示一个相对较长但不无限的时间单位(例如,最近的 1000 条内存访问指令执行时间)。
工作集大小 |W(t, Δ)| 是在时间 t 之前的 Δ 时间窗口内,进程 P 访问过的不同页的数量。
核心思想:
工作集模型基于程序设计的局部性原理 (Principle of Locality)。一个进程在一段时间内倾向于访问一个相对较小的、称为工作集的页集合。随着程序的执行,工作集会缓慢或快速地变化,反映程序当前正在执行的代码段和处理的数据。
工作集模型的目标:
操作系统应该尝试为每个正在运行的进程分配足够多的物理帧来容纳其当前的工作集。即,如果进程 P 的工作集是 W(t, Δ),操作系统应该分配至少 |W(t, Δ)| 个帧给进程 P。
如果一个进程能够将其整个工作集保留在物理内存中,那么它发生缺页中断的概率将大大降低(只会发生在工作集发生改变,需要访问新的页时)。
工作集模型的挑战:
- 如何选择 Δ? Δ 的选择对工作集的大小至关重要。
- Δ 太小:工作集可能不包含进程当前真正需要的全部活跃页,导致频繁缺页。
- Δ 太大:工作集可能包含很多不再活跃的页,导致分配过多内存,浪费资源,并可能减少其他进程可用的帧。
- 选择一个合适的 Δ 是困难的,它通常取决于系统的特性和应用程序的行为。
- 如何有效地跟踪工作集? 在运行时精确地跟踪每个进程在过去 Δ 时间内访问过的所有页并计算其数量是复杂的,需要硬件或操作系统的支持。常见的实现方式包括:
- 使用引用位 (Reference Bit):每个页表项都有一个引用位,硬件在页被访问时设置该位。操作系统周期性地清除这些位,并通过检查哪些位被设置来估计哪些页在最近一段时间内被使用过。通过结合计时或计数,可以近似实现基于时间窗口的跟踪。
- 利用时钟算法或其变种,这些算法隐含地考虑了页的最近使用情况。
尽管精确实现困难,工作集模型提供了一个重要的理论框架:为了避免抖动,系统需要为每个活跃进程提供足够的内存来容纳其工作集,并且系统中所有活跃进程的总工作集大小不应超过可用的物理内存容量。
4. 如何防止或缓解抖动?
防止或缓解抖动的主要思路是确保系统不会进入过度承诺内存的状态,或者在进入该状态时能够及时恢复。这通常通过以下策略实现:
- 工作集分配策略: 操作系统尝试估计每个进程的工作集大小,并为其分配至少那么多帧。如果无法为所有活跃进程分配其估计的工作集所需的帧,则需要采取进一步措施(见策略 3)。实践中,这通常通过 Page Fault Frequency (PFF) 模型来近似实现。
- Page Fault Frequency (PFF) 控制: 这是一种实用的动态分配策略,与工作集模型密切相关。
- 操作系统监控每个进程的缺页中断率。
- 设定两个阈值:
Lower Threshold
和Upper Threshold
。 - 如果一个进程的 PFF 高于
Upper Threshold
:这表明进程可能没有足够的帧,经常发生缺页。操作系统会为其增加分配的帧数(如果系统有空闲帧或可以从其他进程回收帧)。 - 如果一个进程的 PFF 低于
Lower Threshold
:这表明进程可能分配了过多的帧,其当前工作集可能小于分配的帧数。操作系统会为其减少分配的帧数,将回收的帧加入空闲池。 - 如果 PFF 在两个阈值之间:分配的帧数可能比较合适,维持当前数量。
- 这种方法通过调整单个进程的帧数来试图保持其 PFF 在一个可接受的范围内,间接维持了其工作集在内存中。
- 负载控制 (Load Control) / 准入控制 (Admission Control): 这是防止抖动最关键的手段。如果 PFF 控制或其他分配策略发现即使通过调整,所有活跃进程的总内存需求(估计的总工作集大小)仍然超过了物理内存容量,系统就处于潜在的抖动边缘。此时,操作系统必须减少同时活跃的进程数量。
- 这通常通过挂起 (Swapping Out) 一个或多个进程来实现。被挂起的进程其所有页都被换出到磁盘,释放出大量物理帧,从而为剩余的活跃进程提供足够的内存空间来容纳它们的工作集。
- 当系统内存压力缓解(例如,有进程结束或被挂起)时,操作系统可以再将之前挂起的进程重新加载回内存。
- 准入控制是一种前瞻性的负载控制:在允许一个新进程开始运行之前,系统会检查当前活跃进程的总内存需求加上新进程的估计需求是否会超过物理内存容量。如果会,则拒绝启动新进程,直到有足够的内存可用。
- 增加物理内存: 虽然这不是一个操作系统层面的软件策略,但却是最直接有效的硬性解决方案。拥有更多的物理内存可以支持更大的总工作集,从而允许系统运行更多的进程而不会发生抖动。
- 改进程序设计: 编写具有更好内存局部性的程序可以减少工作集的大小,从而降低抖动发生的可能性。这包括使用数组而不是链表进行扫描、将相关的代码和数据放在一起等。
结论
抖动是虚拟内存系统中一种严重的性能瓶颈,其根源在于活跃进程的内存需求超过了物理内存容量。它表现为高缺页率、低 CPU 利用率和极度缓慢的系统响应。
工作集模型提供了一个理论框架,指出了为每个进程提供足够帧以容纳其当前活跃页集的重要性。
为了防止或缓解抖动,操作系统需要:
- 精确或近似地估计进程的内存需求(例如,使用 PFF 模型)。
- 动态地调整分配给进程的物理帧数量。
- 最重要的是,实施负载控制或准入控制,在内存资源不足时,限制同时运行的进程数量,宁可挂起一些进程,也要保证剩余活跃进程能够获得足够的内存来避免抖动。
通过这些策略,操作系统可以有效地管理物理内存,确保系统在多任务环境下保持高效和稳定。