第五篇:《内存管理基础:虚拟内存、交换与缓存》
CPU 的运算离不开内存中的数据。理解 Linux 内存管理机制是分析内存瓶颈、优化应用性能的前提。本文从虚拟内存的地址空间讲起深入解析物理内存与交换分区的关系、Page Cache 与 Buffer Cache 的作用以及 free 命令各项指标的真实含义。最后介绍 swappiness 和大页HugePages两个关键调优参数帮你建立内存管理的完整认知。一、虚拟内存让每个进程都“拥有”整个地址空间1.1 虚拟内存解决了什么问题在早期的计算机系统中程序直接操作物理内存地址。这带来了两个致命问题地址冲突两个程序如果同时运行必须小心翼翼地划分物理内存否则会互相覆盖。内存不足物理内存总是有限的程序大小受限于可用物理内存。虚拟内存Virtual Memory 的出现解决了这两个问题。它为每个进程提供了一个独立的、连续的虚拟地址空间在 64 位系统上通常是 128TB进程认为自己独占了整个内存。而实际上这些虚拟地址通过页表Page Table 映射到物理内存的某个位置。1.2 页表与 MMU虚拟地址到物理地址的翻译当 CPU 执行一条访问内存的指令时它使用的是虚拟地址。这个地址需要被翻译成物理地址才能访问真正的内存芯片。翻译过程由硬件MMU内存管理单元和内核共同完成CPU 将虚拟地址交给 MMU。MMU 查询页表Page Table 找到虚拟地址对应的物理页框号。如果页表项有效MMU 将虚拟地址转换为物理地址完成访问。如果页表项无效该页不在物理内存中触发缺页中断Page Fault 内核从磁盘swap 或文件将数据加载到物理内存。页表是分层组织的Linux 目前支持五级页表每一级页表负责索引下一级最终指向物理页。这种分层设计既节省了页表本身占用的内存又支持了大地址空间。1.3 用户空间与内核空间Linux 将虚拟地址空间划分为两部分用户空间应用程序运行的地方每个进程拥有独立的用户空间。内核空间操作系统内核运行的地方所有进程共享同一个内核空间。在 64 位 Linux 上典型的划分是用户空间占低 128TB内核空间占高 128TB。用户进程不能直接访问内核空间这种隔离保障了系统的安全性。二、物理内存的两种角色匿名页与文件页根据用途物理内存页可以分为两类理解它们的区别是分析内存使用的关键文件页对应的是 Page Cache页面缓存用于缓存文件数据。匿名页则对应进程的私有内存。三、Page Cache 与 Buffer CacheLinux 的“内存加速器”3.1 什么是 Page CachePage Cache页面缓存 是 Linux 内核实现的一种主要磁盘缓存。它的核心思想是将最近访问过的文件数据保留在物理内存中下次需要时直接从内存读取避免访问慢速磁盘。当你 cat 一个文件时文件内容被读入 Page Cache。当你再次 cat 同一个文件时数据直接从 Page Cache 返回速度提升几个数量级。当你写入文件时数据先写入 Page Cache标记为脏页再由内核的 pdflush 线程异步写入磁盘。Page Cache 可以被多个进程共享从而提高内存利用率和系统响应速度。3.2 什么是 Buffer CacheBuffer Cache缓冲区缓存 用于缓存磁盘块block 的元数据。它不缓存文件内容而是缓存磁盘的块信息如超级块、inode 表等减少磁盘 I/O 操作。在现代 Linux 内核中Buffer Cache 和 Page Cache 已经合并管理但 free 命令仍然保留了 buff/cache 列将两者合并显示。3.3 “空闲的内存就是浪费的内存”这是理解 Linux 内存管理最重要的原则。Linux 会尽可能利用空闲物理内存来缓存文件数据以提升系统性能。所以当你看到 free 命令显示内存使用率很高时不必惊慌——大部分可能只是缓存随时可以被回收分配给应用程序。四、free 命令读懂内存的“体检报告”free 命令是最常用的内存查看工具。以 free -h人类可读格式为例$free-htotal usedfreeshared buff/cache available Mem: 15Gi2.1Gi1.2Gi 123Mi 12Gi 13Gi Swap:2.0Gi0.0Ki2.0Gi4.1 各列的含义4.2 available vs free哪个更重要available 是 Linux 内核估算的、在不触发交换swap的情况下可以分配给新应用程序的内存总量。它的计算公式大致为textavailable ≈ free 可回收的 buff/cache 关键结论看内存是否充足请盯着 available 列而不是 free 列。一个系统 free 只有几百 MB但 available 还有几 GB说明内存状态健康——那些“被占用”的内存只是缓存随时可以释放给应用。4.3 手动清理缓存谨慎使用在生产环境中通常不需要手动清理缓存内核会自动管理。但如果为了测试可以通过以下方式释放# 释放 Page Cacheecho1/proc/sys/vm/drop_caches# 释放 dentries 和 inodesecho2/proc/sys/vm/drop_caches# 释放 Page Cache、dentries 和 inodesecho3/proc/sys/vm/drop_caches⚠️ 警告在生产环境执行 drop_caches 会导致所有缓存失效瞬间增加磁盘 I/O可能引起性能抖动。除非有明确测试目的否则不要执行。五、Swap内存的“备胎”当物理内存不足时内核会将部分不常使用的内存页交换swap 到磁盘上的 Swap 分区或 Swap 文件。这相当于用磁盘空间“冒充”内存让系统能在内存不足时继续运行。5.1 Swap 的工作原理Swap 的交换过程由内核的调页算法Paging 和交换技术Swapping 共同完成调页Paging 将内存中最近不常使用的页面page 换出到磁盘把常使用的页面保留在内存中。交换Swapping 将整个进程的内存映像换出到磁盘在现代 Linux 中较少使用。5.2 何时使用 Swapvmstat 命令的 siswap in和 soswap out列可以监控 Swap 的使用情况$vmstat1procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpdfreebuff cache si so bi boincs us syidwa st1010240500002000030000000102050080002556820si每秒从磁盘交换到内存的页数KB/秒so每秒从内存交换到磁盘的页数KB/秒关键原则当 si 和 so 长期大于 0 时说明系统内存不足已经频繁使用 Swap。这会消耗大量磁盘 I/O 和 CPU 资源严重影响性能。 注意swpd 列显示的是当前已使用的 Swap 总量KB。如果 swpd 很大但 si/so 为 0说明历史上曾使用过 Swap但当前没有交换活动——这通常不是问题。5.3 swappiness控制内核“用 Swap 的冲动”swappiness 是 Linux 内核参数控制系统主动使用 Swap 的倾向。取值范围是 0 到 100默认值通常是 60。值越高内核越倾向于将不活跃的内存页交换到磁盘以释放物理内存用于 Page Cache。值越低内核越倾向于保留内存中的匿名页减少 Swap 使用。查看当前值cat/proc/sys/vm/swappiness临时调整sudosysctlvm.swappiness10永久调整写入 /etc/sysctl.conftextvm.swappiness 10典型场景的 swappiness 建议值六、大页HugePages与透明大页THP6.1 为什么需要大页Linux 默认的内存页大小是 4KB。对于内存密集型应用如数据库页表会变得非常庞大——一个使用 64GB 内存的进程需要约 1600 万个页表项。这会消耗大量内存并导致 TLBTranslation Lookaside Buffer页表缓存 频繁未命中降低性能。大页HugePages 将页面大小从 4KB 提升到 2MB或 1GB从而减少页表项数量64GB 内存只需要约 3.2 万个页表项。减少 TLB 未命中提升内存访问速度。6.2 HugePages vs 透明大页THPTHP 的争议THP 虽然简化了管理但对于访问模式离散的负载如数据库可能因为频繁的页面合并和拆分导致性能下降甚至系统不稳定。许多数据库官方文档如 MySQL、MongoDB建议在生产环境禁用 THP。禁用 THPechonever/sys/kernel/mm/transparent_hugepage/enabledechonever/sys/kernel/mm/transparent_hugepage/defrag七、小结虚拟内存通过页表让每个进程拥有独立的地址空间MMU 负责将虚拟地址翻译为物理地址。Page Cache 和 Buffer Cache 利用空闲内存缓存文件数据提升 I/O 性能。free 命令的 available 列才是真正可用的内存。Swap 是内存的“备胎”si/so 长期大于 0 说明内存不足。swappiness 控制内核使用 Swap 的倾向。大页HugePages 减少页表开销和 TLB 未命中但 THP 可能引入风险需根据场景谨慎选择