Linux pagecache介绍

Linux 的 Page Cache 是内核用于缓存磁盘数据的一种机制,通过将磁盘文件的内容暂存到内存中,显著提升系统性能。以下是其核心要点:


1. 基本概念

  • 作用:减少磁盘 I/O 操作,加速文件读写。
  • 存储内容:缓存磁盘文件的数据块(以内存页为单位,通常 4KB)。
  • 归属:由内核管理,对用户透明,应用程序无需直接操作。

2. 工作原理

读操作

  • 当应用程序读取文件时,内核优先检查 Page Cache:
    • 命中缓存:直接从内存返回数据,无需访问磁盘。
    • 未命中:从磁盘读取数据,并缓存到 Page Cache 供后续使用。

写操作

  • 默认使用 Writeback(延迟写) 策略:
    1. 数据先写入 Page Cache,标记为“脏页”(Dirty Page)。
    2. 内核定期(或触发同步条件时)将脏页写回磁盘。
    3. 后台线程(如 kswapd)负责刷脏页,确保数据最终持久化。
  • 同步写入:通过 fsync()O_SYNC 标志强制立即写回磁盘,牺牲性能保障一致性。

3. 内存管理

  • 内存回收
    • 当系统内存不足时,内核根据 LRU(最近最少使用) 等算法淘汰旧缓存页。
    • 优先释放“干净页”(未被修改的缓存),脏页需先写回磁盘再释放。
  • 调整策略:通过 /proc/sys/vm/ 下的参数(如 swappinessdirty_ratio)可调节缓存回收和刷脏页的行为。

4. 相关工具

  • 查看缓存使用
    • free -h:查看 buff/cache 列,显示 Page Cache 和 Buffer Cache 的总量。
    • vmstat 1:监控 cachedirty 字段。
    • sar -r 1:查看内存和缓存使用情况。
  • 手动清理缓存
    1
    2
    3
    4
    # 释放干净页(不影响脏页)
    echo 1 > /proc/sys/vm/drop_caches
    # 释放所有页(包含脏页需先刷盘)
    echo 3 > /proc/sys/vm/drop_caches

    注意:生产环境慎用,可能导致性能波动。


5. 应用场景与优化

  • 优势
    • 加速重复文件访问(如 Web 服务器的静态资源)。
    • 合并多次写操作,减少磁盘 I/O 次数。
  • 注意事项
    • 数据库系统:可能绕过 Page Cache(如 MySQL 使用 O_DIRECT 直接 I/O),避免双重缓存。
    • 实时性要求高:可通过 sync()fsync() 确保关键数据及时落盘。
    • 大内存机器:合理配置缓存策略,避免过多内存被缓存占用。

6. Page Cache 与 Buffer Cache

  • 历史区别
    • Buffer Cache:缓存磁盘块(原始块设备数据)。
    • Page Cache:缓存文件页(基于文件系统的抽象)。
  • 现状:两者在现代内核中统一管理,/proc/meminfo 中的 Buffers 通常指块设备元数据缓存,Cached 指文件内容缓存。

总结

Page Cache 是 Linux 提升 I/O 性能的核心机制,通过内存换速度,平衡了磁盘访问的延迟问题。理解其工作原理有助于优化系统配置(如调整刷脏页阈值)或设计应用策略(如选择直接 I/O 或缓存 I/O)。

Linux /proc/meminfo详细解析

以下是关于 Linux /proc/meminfo 文件的详细解析。该文件记录了系统内存使用情况的详细信息,是分析内存性能、排查内存问题的重要工具。


1. /proc/meminfo 概述

  • 位置:虚拟文件,位于 /proc/meminfo
  • 作用:提供系统内存的实时统计信息,包括物理内存、交换空间(Swap)、内核内存分配、缓存和缓冲区等。
  • 查看方法
    1
    cat /proc/meminfo

2. 核心字段解析

以下单位为 kB(千字节),部分字段可能因内核版本略有差异。


(1) 物理内存(Physical Memory)

  • MemTotal
    系统总物理内存(不包括内核保留的少量内存)。
    示例:MemTotal: 16266004 kB(约 15.5 GB)。

  • MemFree
    完全未使用的物理内存(空闲内存)。
    注意:MemFree 低不一定是问题,Linux 会尽可能利用内存做缓存。

  • MemAvailable (内核 3.14+ 引入)
    系统可分配给应用程序的估计可用内存,包含 MemFree + 可回收的缓存/缓冲区。
    MemFree 更准确反映实际可用内存。


(2) 缓存与缓冲区(Caches & Buffers)

  • Buffers
    临时存储原始磁盘块(块设备 I/O 的缓冲区),如文件系统元数据(目录结构等)。

  • Cached
    文件系统的页缓存(Page Cache),缓存已读取的文件内容,可加速重复访问。
    示例:Cached: 4200300 kB(约 4 GB)。

  • SwapCached
    曾经被换出(Swap Out)后又换入(Swap In)的内存,仍保留在 Swap 中的缓存。
    若此值较高,说明系统曾发生内存紧张。

  • SReclaimable
    Slab 内存中可回收的部分(如 dentry、inode 缓存)。
    示例:SReclaimable: 150200 kB

  • Shmem
    共享内存(Shared Memory)和 tmpfs 使用的内存(如 /dev/shm 或 Docker 容器文件系统)。


(3) 内核内存(Kernel Memory)

  • Slab
    内核数据结构(如 dentry、inode、网络协议栈等)占用的内存 = SReclaimable + SUnreclaim

  • KernelStack
    内核栈内存(每个线程的内核栈占用约 16KB)。

  • PageTables
    页表(Page Table)占用的内存,进程越多或内存映射越复杂,此值越大。

  • VmallocUsed
    通过 vmalloc() 分配的内核虚拟地址空间大小(如内核模块、设备驱动)。


(4) 交换空间(Swap)

  • SwapTotal
    交换空间总大小。

  • SwapFree
    空闲的交换空间。


(5) 其他关键字段

  • Active
    最近活跃使用的内存(包括缓存和应用程序内存)。

  • Inactive
    较久未使用的内存(可被回收)。

  • Dirty
    等待写回磁盘的脏页大小(单位 kB)。

  • Writeback
    正在写回磁盘的脏页大小。

  • Mapped
    被映射到进程地址空间的文件大小(如共享库)。

  • AnonPages
    匿名页(如进程堆、栈等不与文件关联的内存)。

  • CommitLimitCommitted_AS

    • CommitLimit:系统允许分配的总内存(物理内存 + Swap)的阈值。
    • Committed_AS:当前已分配(包括承诺分配)的内存总量。
      Committed_AS 接近 CommitLimit,可能触发 OOM(Out-of-Memory)。

3. 示例解读

查看 /proc/meminfo 片段

1
2
3
4
5
6
7
8
9
10
11
12
MemTotal:       16266004 kB
MemFree: 524304 kB
MemAvailable: 4321500 kB
Buffers: 214116 kB
Cached: 4200300 kB
SwapTotal: 2097148 kB
SwapFree: 2097148 kB
Shmem: 318344 kB
Slab: 287644 kB
SReclaimable: 150200 kB
SUnreclaim: 137444 kB
...

分析

  1. 物理内存:总内存约 15.5 GB(MemTotal),空闲内存约 512 MB(MemFree),但可用内存约 4.2 GB(MemAvailable),说明大部分内存被缓存占用(Cached 4 GB)。
  2. Swap:未使用(SwapFree = SwapTotal),说明当前内存充足。
  3. 内核内存:Slab 占用约 287 MB,其中 150 MB 可回收(SReclaimable)。
  4. 共享内存:约 318 MB(Shmem),可能来自共享库或 tmpfs。

4. 常见问题排查

(1) 内存泄漏

  • 现象MemAvailable 持续下降,SlabAnonPages 异常增长。
  • 工具:结合 pstopsmem 分析进程内存占用。

(2) 交换空间使用高

  • 现象SwapFree 减少,SwapCached 增加。
  • 原因:物理内存不足,触发 Swap。
  • 优化:增加物理内存或减少内存占用。

(3) 缓存占用过高

  • 现象CachedBuffers 占用大量内存。
  • 处理:通常无需干预,Linux 会自动回收。紧急时可手动清理:
    1
    2
    3
    echo 1 > /proc/sys/vm/drop_caches  # 清理页缓存
    echo 2 > /proc/sys/vm/drop_caches # 清理目录项和inode缓存
    echo 3 > /proc/sys/vm/drop_caches # 清理所有缓存

5. 相关工具

  • **free**:显示 MemSwap 使用情况,数据来自 /proc/meminfo
  • **vmstat**:监控内存、Swap、I/O 等。
  • **slabtop**:查看 Slab 内存的详细分配。
  • **smem**:按进程统计内存使用。

总结

/proc/meminfo 是理解 Linux 内存分配的核心文件,通过分析其字段可以:

  • 判断内存是否充足(关注 MemAvailable)。
  • 识别缓存或内核内存泄漏(观察 SlabAnonPages)。
  • 监控 Swap 使用情况。
    结合工具(如 freevmstat)能更高效地定位内存相关问题。