Linux overcommit 为虚拟内存承诺设定政策
Linux 的 overcommit 政策控制某些虚拟内存承诺是否可以获准,和分配常驻物理页、选择 OOM 牺牲进程、执行容器内存限制并不是同一件事。一次成功申请可能早于实际物理需求,但这不表示所有分配都没有成本,也不保证后续访问在任何资源约束下都能成功。分析时应把承诺、驻留和故障处理分别记录,而不是都称为“剩余内存”。 虚拟承诺不同于实际驻留 malloc 等分配器可能通过 brk 或 mmap 取得内存,也可能直接复用已有内存区,不发起新的系统调用。匿名页通常按需填入,但地址空间元数据、页表以及实际缺页过程仍然消耗资源。具体成本取决于应用申请什么、访问什么,不能把延迟分配简化成近乎免费地运行整个进程。 Committed_AS 是记账数量,不是所有进程常驻集之和,也不是当前内存压力读数。映射类型会影响成本:私有可写映射可能在页面尚未全部驻留时就形成承诺,普通共享或只读文件映射则采用不同规则。因此,虚拟大小很大的进程未必就是物理内存短缺的责任方,应同时查看实际使用和对应记账范围。 三种准入政策 模式零是默认启发式政策,拒绝明显超额的申请,同时允许超过简单常驻内存预算的分配。它的判断不等于为每个获准字节准备专属 RAM。模式一跳过 overcommit 准入检查,有助于某些稀疏工作负载,但地址空间上限、映射数量以及其他分配失败仍然存在,不能描述成任何荒谬请求都会被无条件接受。 模式二执行更严格的承诺记账。名义 CommitLimit 来自交换空间加上配置的内存额度:比例计算会扣除预留给 hugetlb 的内存,非零 overcommit_kbytes 则用绝对额度代替比例。内核保留量与调用上下文还会影响实际准入。因此,CommitLimit 与 Committed_AS 的差值是有用背景,不是保证任意调用者都能一次申请成功的最大值,也不是当前可用物理内存。 需要记账的分配如果无法纳入预算,可能立即返回 ENOMEM,使部分容量问题更早暴露,包括 fork 和后续改变映射权限所需的承诺。fork 记账与具体映射及写时复制义务有关,并不是简单把父进程常驻集乘二。有些应用有意保留稀疏地址空间,因此政策变化可能影响启动,即使它们预计不会触碰所有页面。 严格记账不是 OOM 免疫 模式二降低一类超额承诺风险,却不会覆盖 cgroup 内存限制、NUMA 约束、其他内核分配以及所有后续需求。任务仍可能遇到内存分配失败或 OOM 事件。不能承诺选了模式二,某个业务工作进程就绝不会被杀,更不能把这个模式当成服务可靠性的单一开关。 ...