Linux 内存控制参数汇总

sysctl 控制参数

下表列出一些常见的 Linux (Kernel 5.3)内存相关的调节参数,具体参数根据内核版本可能有所不同,其使用场景和含义需要查看对应内核版本的相关文档

Option Default Value Description Examples
vm.dirty_background_bytes
/proc/sys/vm/dirty_background_bytes
0 bytes 0 表示使用 vm.dirty_background_ratio 来决定将内存脏页(Memroy Dirty Pages)写回磁盘的阈值而不是使用 vm.dirty_background_bytes
- 设置为相对较高的值,会使内存中的数据延迟写入磁盘,产生较小的 IOPS,但是可能会导致数据不一致或丢失
- 设置为相对较低的值,会使内存数据及时写入磁盘,导致 IOPS 较高,数据丢失或不一致的风险较低
vm.dirty_background_ratio
/proc/sys/vm/dirty_background_ratio
10 默认当内存脏页数据达到内存大小的 10% 时,在后台触发 per-bdi writeback(Linux 早期(Linux 内核 3.0 之前)由 pdflush 负责处理脏页(dirty pages)写回磁盘的机制)将脏页数据写回磁盘。回写(Write-Back)操作由统一的内核线程 kworkerflush-<设备名> 处理
vm.dirty_bytes
/proc/sys/vm/dirty_bytes
0 bytes 定义强制写回的脏页阈值(以字节为单位)。
vm.dirty_ratio
/proc/sys/vm/dirty_ratio
20 定义强制写回的脏页阈值(以总内存的百分比表示)。
vm.dirty_writeback_centisecs
/proc/sys/vm/dirty_writeback_centisecs
500 定义写回线程的执行间隔(以百分之一秒为单位)。
vm.dirty_expire_centisecs
/proc/sys/vm/dirty_expire_centisecs
3000 定义脏页的最大“年龄”(超过这个时间的脏页会被优先写回)。
如需手动执行写回操作,可以使用命令 sync
vm.min_free_kbytes
/proc/sys/vm/min_free_kbytes
通常为 min_free_kbytes = sqrt(总内存 * 16) 控制系统保留的最小空闲内存量(以 KB 为单位),确保系统在内存压力下仍有足够的内存用于关键操作,如处理中断、内核操作等。
如果设置过小
- 系统可能在内存紧张时无法及时回收内存,导致性能下降。
- 网络流量或 I/O 密集型任务可能因内存分配失败而中断。
- 可能增加系统触发 OOM(Out-Of-Memory)的风险。
如果设置过大
- 系统可用内存减少,因为更多内存被预留。
- 可能导致用户空间任务频繁触发内存回收,降低整体性能。
vm.watermark_scale_factor
/proc/sys/vm/watermark_scale_factor
10 内核的内存水位标记( watermarks )机制
vm.watermark_boost_factor
/proc/sys/vm/watermark_boost_factor
15000 在内存压力下临时提升水位,保证一定的空闲内存。
vm.percpu_pagelist_high_fraction
/proc/sys/vm/percpu_pagelist_high_fraction
0 vm.percpu_pagelist_high_fraction
vm.overcommit_memory
/proc/sys/vm/overcommit_memory
vm.overcommit_ratio
vm.overcommit_kbytes
Linux 内存 Overcommit 机制详解
vm.swappiness
/proc/sys/vm/swappiness
60 控制 内核在内存不足前主动使用 Swap 的程度,取值范围:0 - 100
- 0尽可能 **不使用 Swap** ,只有在内存耗尽时才使用(适合数据库、低延迟应用)。<br/>- 100` : 尽可能 频繁使用 Swap(适合桌面系统)
vm.vfs_cache_pressure 100 vm.vfs_cache_pressure
vm.admin_reserve_kbytes
/proc/sys/vm/admin_reserve_kbytes
3% Free Pages 为系统管理员保留一定量的内存,以防止在内存紧张时关键的管理任务(如登录、执行命令等)无法正常运行。这部分内存不会被普通用户进程占用,即使在系统内存紧张时也会保留。
memory_failure_early_kill
/proc/sys/vm/memory_failure_early_kill
0 用于控制在发生内存故障时,系统是否立即将有问题的内存页标记为不可用,并杀死访问该内存的进程。
- 默认值是 0 ,表示不立即杀死进程。
- 启用后(值为 1) 当检测到内存错误时,系统会尽早杀死访问该内存的进程,以避免更多的系统崩溃或错误发生。
memory_failure_recovery
/proc/sys/vm/memory_failure_recovery
1 当检测到内存故障时,系统可以尝试 恢复错误的内存页
- 默认值是 1 ,表示启用内存恢复机制。
- 禁用后(值为 0) : 系统不尝试恢复内存错误,可能会更直接地采取 杀死进程标记内存为不可用 的操作。
/proc/sys/vm/drop_caches 默认值始终为 0 允许管理员手动清理 Linux 内存缓存,包括:
- Page Cache(页面缓存) : 主要用于加速文件读取。
- Dentry Cache(目录项缓存) : 记录文件路径信息,加快目录访问。
- Inode Cache(索引节点缓存) : 记录文件元数据,如大小、权限等。
drop_caches 不会影响进程已使用的内存,只是释放 内核缓存 适用于 测试、性能调优、观察内存使用情况 ,但不建议频繁使用。
可选值包括:
- 1 : 清理 Page Cache ,释放文件数据缓存
- 2 : 清理 DentryInode Cache,释放目录路径和文件元数据缓存
- 3 : 清理 Page CacheDentryInode Cache(全部)
建议同步数据到磁盘(sync)后清理,防止数据丢失
/proc/sys/vm/compact_memory 默认值始终为 0 compact_memory

vm.watermark_scale_factor

vm.watermark_scale_factor (/proc/sys/vm/watermark_scale_factor)是 Linux 内核中的一个虚拟内存管理参数,它影响内核的内存水位标记( watermarks )机制。内存水位标记用于决定何时触发内存回收(如回收页缓存或启动交换操作)。通过调整该参数,可以控制内核在内存压力下的行为和回收策略。

Linux 内核为每个内存区域(zone)定义了三个水位标记:

  1. min(最低水位)

    当可用内存低于 min 时,内核强制触发回收机制,尽一切可能释放内存。

  2. low(低水位)

    内核尝试开始回收内存,但允许正常分配。

  3. high(高水位)

    可用内存高于 high 时,内核不会主动回收内存。

这些水位标记在 /proc/zoneinfo 中可以查看:

# cat /proc/zoneinfo | grep -E "Node|min|low|high"
Node 0, zone DMA
min 8
low 10
high 12
Node 0, zone DMA32
min 1532
low 1915
high 2298
Node 0, zone Normal
min 15355
low 19193
high 23032

vm.watermark_scale_factor 是一个百分比值(默认值为 10,表示 10% ),用于调整内存水位的敏感度。具体来说:

  • 它决定了内存水位的范围(highlow 之间的差距)。

  • 值越大,水位范围越大,内核对内存压力的响应越迟钝。

  • 值越小,水位范围越小,内核对内存压力的响应越敏感。

内存水位的计算方式如下:

high = min_free_kbytes + (总内存 * watermark_scale_factor / 10000)
low = high - (总内存 * watermark_scale_factor / 10000)
min = low - (总内存 * watermark_scale_factor / 10000)

增大 watermark_scale_factor

  • 内存水位范围变大,内核对内存压力的响应变慢。
  • 适用于内存充足且希望减少内存回收频率的场景。
  • 过高值 可能导致系统在内存压力下响应过慢,增加 OOM(Out of Memory)风险。

减小 watermark_scale_factor

  • 内存水位范围变小,内核对内存压力的响应变快。

  • 适用于内存紧张且需要快速回收内存的场景。

  • 过低值 可能导致内核频繁回收内存,增加系统开销。

vm.percpu_pagelist_high_fraction

从 Linux 5.16 及以后,vm.percpu_pagelist_fraction 已被移除,取而代之的是 vm.percpu_pagelist_high_fraction,并且 PCP(Per-CPU Page List)大小的计算方式发生了变化。

什么是 PCP(Per-CPU Page List)?

Linux 内核的物理页框管理(Buddy System)采用 PCP(Per-CPU Page List,每 CPU 页列表) 机制,为每个 CPU 维护一个 独立的 页缓存,以减少多个 CPU 争夺全局锁,提高内存分配效率。

PCP 的作用

  • 通过为每个 CPU 保留一定数量的空闲页,减少内存分配时对全局锁争用,加快小规模页分配,从而提高多核系统上的内存分配性能。
  • 提高缓存命中率,避免频繁访问 Buddy System。每个 CPU 都有自己的空闲页列表,减少了多个 CPU 同时访问全局空闲列表时的锁争用。

PCP 主要参数

  • low : 低水位,低于此值时,系统会回收页。
  • high : 高水位,达到此值时,释放多余页给 Buddy System。

vm.percpu_pagelist_high_fraction 控制 Per-CPU Page List(每 CPU 页列表)的上限(high limit) ,限制 PCP 过大导致的内存浪费。

Linux 内存 Overcommit 机制详解

在 Linux 内核中,Overcommit 机制决定了系统如何管理 虚拟内存(Virtual Memory) 申请,特别是当进程申请的内存超过物理 RAM + Swap 时的处理策略。

Linux 内核的 Overcommit 机制允许系统分配比实际物理内存更多的虚拟内存。这种机制基于以下假设:

  • 并非所有分配的内存都会被实际使用。

  • 应用程序可能会申请大量内存,但实际使用的只是其中一部分。

相关参数:

  • vm.overcommit_memory —— 控制 Overcommit 策略(是否允许超额分配)。
  • vm.overcommit_ratio —— 影响可分配内存的计算。
  • vm.overcommit_kbytes —— 手动设置可 Overcommit 的最大内存(部分新内核支持)。

vm.overcommit_memory 是一个整数值,用于控制内核的内存分配策略。它有以下三种模式:

  • 0(默认值) : Heuristic Overcommit(启发式 Overcommit)。

    • 内核会根据当前系统的内存使用情况,使用启发式算法(基于历史数据)来决定是否允许内存分配。

    • 允许进程请求比实际 RAM 多的内存

    • 如果系统空闲内存较少,可能会拒绝内存分配请求。

    • 这是最常用的模式,适用于大多数场景

  • 1 : Always Overcommit(总是允许 Overcommit)。

    • 内核总是允许内存分配请求,无论当前内存使用情况如何。程可以分配 任意大小 的虚拟内存,哪怕物理 RAM 和 Swap 不够。

    • 这种模式下,系统可能会分配比实际物理内存更多的虚拟内存。

    • 适用于内存密集型应用,但存在 OOM(Out-Of-Memory)风险。

  • 2 : Strict Overcommit(禁止 Overcommit)。

    • 内核会严格限制内存分配,确保分配的内存不超过 overcommit_ratioovercommit_kbytes 设置的限制。

    • 进程申请超出 CommitLimit 直接 失败(返回 ENOMEM)

    • 这种模式下,系统不会分配超过物理内存和交换空间总和的内存。

    • 适用于对内存使用要求严格的场景。

vm.overcommit_memory = 2 时,vm.overcommit_ratio 决定 CommitLimit (可分配的最大虚拟内存) 。overcommit_ratio 是一个百分比值,用于在 overcommit_memory=2 模式下限制内存分配。它定义了系统可以分配的内存总量与物理内存的比例。 默认值 :通常为 50(即 50%)。

允许分配的内存总量 = 物理内存 × (overcommit_ratio / 100) + 交换空间

例如,如果物理内存为 16GB,overcommit_ratio=50,交换空间为 4GB,则允许分配的内存总量为:

16GB × 0.5 + 4GB = 12GB

查看 CommitLimit 的值:

# cat /proc/meminfo | grep -E "MemTotal|SwapTotal|CommitLimit"
MemTotal: 32680152 kB
SwapTotal: 8388604 kB
CommitLimit: 24728680 kB

vm.overcommit_ratio 仅在 vm.overcommit_memory=2 时生效。在其他模式下(vm.overcommit_memory=01),vm.overcommit_ratio 不会起作用。

vm.overcommit_kbytes 直接指定可 Overcommit 的最大内存大小 (部分新内核支持)。

vfs_cache_pressure

VFS(Virtual File System) 是 Linux 内核中的一个抽象层,用于支持多种文件系统(如 ext4XFSNTFS 等)。VFS 缓存主要包括:

  • 目录项缓存(dentry cache : 缓存目录项(dentry),用于快速查找文件路径。

  • inode 缓存 : 缓存文件的元数据(如权限、大小、时间戳等)。

VFS 缓存可以显著提高文件系统的访问速度,因为访问缓存中的数据比从磁盘读取要快得多。

vm.vfs_cache_pressure 控制 内核回收 VFS(Virtual File System)缓存的倾向 。取值范围包括:

行为 适用场景
0-50 降低 VFS 缓存回收率,更倾向于保留 dentry/inode 缓存
- 更多 VFS 缓存,加速文件系统访问,但可能会导致 Swap 增加。
适合 大量文件操作(NFS 服务器、文件服务器)
100 默认值,平衡回收 VFS 缓存与 Page Cache 适用于 通用服务器
>100 更积极回收 VFS 缓存,更快释放 inode/dentry 资源
- 减少 VFS 缓存,腾出更多内存给其他任务,但可能会导致频繁的 I/O 操作,降低文件访问效率。
适合 低内存服务器

使用以下命令可以查看 VFS 缓存占用

# cat /proc/meminfo | grep -E "Cached|Dirty|Writeback"
Cached: 23405312 kB
SwapCached: 14760 kB
Dirty: 3788 kB
Writeback: 0 kB
WritebackTmp: 0 kB

compact_memory

/proc/sys/vm/compact_memory 是一个 Linux 内核的内存调优参数,用于 触发内存压缩操作 。在内存碎片化较严重的情况下,调用此参数可以 强制内核进行内存压缩 ,使得内存中的空闲区域变得更加连续,从而提高系统的内存使用效率。

内存压缩是指将不再使用的内存区域合并或回收,目的是减少内存的碎片化,避免内存浪费,并且为系统中的其他进程提供更多可用的内存。

Linux 内核会自动处理内存碎片化问题,但在以下情况中,可以手动触发内存压缩:

  • 内存碎片化严重 :系统在长期运行或高负载的情况下可能导致内存碎片化,手动触发内存压缩可以解决这个问题。
  • 内存紧张 :在内存不足或交换空间使用较多时,可以通过压缩内存来释放更多可用内存,减少对交换空间的依赖。

若要触发内存压缩,可以写入 1/proc/sys/vm/compact_memory

echo 1 > /proc/sys/vm/compact_memory

这会触发内核进行内存压缩,尝试减少内存碎片化。系统会尝试将空闲内存区域合并,并释放不再使用的内存块。

OOM

Linux OOM(Out Of Memory) 是指 Linux 内核检测到系统内存耗尽 时触发的机制。当可用内存不足且无法通过 回收缓存交换内存 释放更多资源时,Linux 内核会启动 OOM-Killer(OOM 杀手),选择并杀死某些进程,以释放内存,使系统继续运行。

OOM 主要发生在以下情况下:

  • 物理内存不足 且 swap(交换分区)空间也耗尽
  • 进程请求的内存超过系统可以提供的可用内存(例如 malloc() 失败)
  • 某个进程使用了过多内存,导致其他进程无法正常运行(通常称为 内存泄漏

OOM-Killer 工作原理

当系统内存不足时,OOM-Killer 需要决定 杀死哪个进程 以释放最多的内存,同时尽可能减少对系统稳定性的影响。它会根据 OOM 分数(oom_score) 来评估进程的优先级,选择合适的目标。

  • OOM Score 计算方式

    Linux 通过 /proc/[PID]/oom_score 计算每个进程的 OOM 分数,决定哪个进程最适合被杀死。计算方式包括:

    • 进程的 实际内存使用量(包括 RSS 和 swap)
    • 进程的 优先级(nice 值)
    • 进程是否有 特殊权限(例如 root 用户的进程通常优先级较低,不会被轻易杀死)
    • 进程是否 手动调整了 OOM 权重( oom_score_adj

    查看进程的 OOM Score:

    cat /proc/$(pgrep -f <进程名>)/oom_score

  • 调整进程的 OOM Score

    可以通过 /proc/[PID]/oom_score_adj 影响 OOM-Killer 的决策:

    echo -1000 > /proc/$(pgrep -f <进程名>)/oom_score_adj  # 降低 OOM 优先级
    echo 1000 > /proc/$(pgrep -f <进程名>)/oom_score_adj # 增加 OOM 优先级

    • -1000 : 表示 永不杀死 该进程(适用于重要进程,如 sshd)。
    • 1000 : 表示 更容易被杀死
  • oom_dump_tasks 参数

    /proc/sys/vm/oom_dump_tasks 控制 当 OOM-Killer 触发时,是否记录被终止的进程信息。该参数的作用是 方便系统管理员分析 OOM 发生时的内存使用情况,帮助排查问题

    • 默认值: 1(启用) 。当发生 OOM 时,内核会记录 所有进程的内存使用信息 到系统日志。
    • 禁用(0) : 发生 OOM 时,不会记录进程信息,日志会更简洁,但不利于排查问题。
  • oom_kill_allocating_task 参数

    /proc/sys/vm/oom_kill_allocating_task 控制 OOM Killer 是否优先杀死正在申请内存的进程(即导致 OOM 的那个进程)

    • 0(默认值) :OOM Killer 按 OOM 评分选择要杀死的进程,不一定是触发 OOM 的进程。
    • 1 :直接杀死 触发 OOM 事件的进程(即当前正在申请内存但失败的进程)