一种假装物理内存约束不存在、让分配保持廉价的策略。

Linux 的 overcommit 是内核的一场豪赌

调整 vm.overcommit_memory,把从内核盲目乐观里让出的那部分判断交回你自己的预算,最终决定谁在 OOM 时被牺牲。 为什么 malloc 很少失败 vm.overcommit_memory 默认为 0,处在启发式模式:它几乎对每一个 mmap 和 malloc 都说好,只要系统还大概承担得起;只有当内存真正吃紧时才拒绝。因为虚拟内存的承诺本身几乎零成本,可容纳的页又是点到即给,所以绝大多数分配都会成功,普通进程以近乎免费的方式活得好好的。这份慷慨的代价是内核可以超卖远多于物理内存。它赌你不会真正写满每一页;一旦太多字节真的落到内存里,总有人要用一次 OOM kill 来买单。 那个开关 vm.overcommit_memory 让你选择由谁来拿预算。默认 0 是启发式超卖:内核只拒绝那些明显不可能兑现的请求,其余几乎照单全收,赌的是多数进程永远不会触碰自己申请的每一个字节。设为 1 表示总是允许超卖:内核几乎不再设防,适合那些映射巨大但大多保持稀疏、长期不触碰的程序,代价是所有失败都被推迟到回收路径或杀手裁决那一刻。设为 2 则是严格记账:凡是超出 CommitLimit 的申请都会在调用当场以内存不足失败,这个上限大致等于交换空间加上物理内存乘以 overcommit_ratio 的比例,当 overcommit_kbytes 非零时以后者为准。两种极端都不免费:总是超卖会把压力藏到整机停顿才爆发,严格记账则会让那些申请慷慨但实际触碰很少的程序直接启动失败,应当按你想控制的风险来选。 启发式对严格上限 当账最终要平的那天到来,真正的问题是谁来买单。启发式模式下,内核会继续超卖,并在内存压力下随机挑一个牺牲品;严格模式下,边界事先画好,失败在 malloc 这一步就浮出水面,由运维而不是调度器决定哪个进程去吞这枚 OOM kill。容器与虚拟机通常会把它调成受控值:一台代表许多 guest 一起超卖的主机,在需求同时冲高时可能把自己的底盘一起压垮。笔记本可以大方一点;而一台绝对不能悄悄丢掉某个工作进程的产线上,就应当把选择说得明明白白。 坏掉的样子 在默认启发式模式下,最让人困惑的故障是:一次巨大的 malloc 或 mmap 明明返回成功,进程却在稍后被杀掉。申请瞬间还没有触碰任何页面,看起来一切正常;等进程真正写入这些页面、内存开始吃紧,内核杀手就会挑选一个牺牲品,而它往往不是当初超额申请的那个,而是旁边体积最大的进程。日志里只剩一句内存不足杀进程,却找不到任何一次分配失败,排查很容易追错二进制文件,真正的超卖源头反而藏在身后。 ...

十二月 18, 2027 · 2 分钟 · XB Field Notes
一块运行时读写内核参数的控制台。

sysctl 在运行中调整内核

sysctl 不是一种配置文件的格式。它是内核参数表的一个实时视图,可以用点号分隔的名字访问,并且镜像在 /proc/sys 下——所以读一个值和写一个值,字面意义上就是读、写一个伪文件。这正是 sysctl -w 立刻生效的原因,也正是用这种方式设下的东西一条都活不过重启的原因。 张力全在后半段:持久化。运行时接口诚实而即时,而那个本该让设置留下来的文件,却要面对文件名优先级、两种实现对 /etc/sysctl.conf 的分歧,以及一种「这一行其实什么都没做」的失效方式。 一个键就是活表里的一条路径 每个点号键都对应一个伪文件:net.ipv4.ip_forward 对应 /proc/sys/net/ipv4/ip_forward;sysctl(8) 也指出,sysctl 支持依赖 procfs。sysctl -a 会枚举整张表,跳过已废弃和「禁止读取」的参数;而这些排除项里就有一条本身就是警告:stat_refresh 不返回任何值,但读它会把 per-CPU 的 VM 统计刷一遍——所以「把所有东西读一遍」并不总是免费的。 因为这是一张活表而不是存下来的配置,键的集合稳定,值不稳定。在录制 fixture 的这台 macOS 上,sysctl -a 返回了 1917 个键、分布在 14 个顶层命名空间里;连续读两次,键集合完全一致,但有 47 行的值变了。读写走同一个处理器:不存在的键给 ENOENT,只读的键拒绝写入,无法解析的值给 EINVAL。没有任何守护进程持有状态。 先运行时,后持久化 sysctl -w key=value 作用在正在运行的内核上,哪里都不写,所以它适合用来试。要持久化就得有一个 init 会去读的文件,而这里两种实现是有分歧的:procps 的 sysctl --system 会依次读 /etc/sysctl.d、/run/sysctl.d、/usr/local/lib/sysctl.d、/usr/lib/sysctl.d、/lib/sysctl.d,最后读 /etc/sysctl.conf;而 systemd-sysctl 只读那些 drop-in 目录,按 sysctl.conf(5) 的说法,它根本不用 /etc/sysctl.conf。 ...

十一月 22, 2026 · 1 分钟 · XB Field Notes