ulimit -m 在现代 linux 中无效,因内核自 2.4.30/2.6.9 起忽略 rlimit_rss,posix 已将其标记为 obsolete;真正有效的是 cgroups v2 的 memorymax(如 systemd-run --scope -p memorymax=512m)。

ulimit -m 不能锁定物理内存上限,且在现代 Linux 中基本无效。这是关键前提,必须先澄清——否则所有操作都建立在错误基础上。
为什么 ulimit -m 不起作用?
Linux 内核从 2.4.30 / 2.6.9 起已忽略 ulimit -m(即 RLIMIT_RSS)的设置。它不再限制进程实际能使用的物理内存(RSS),内核会直接无视该限制值。POSIX 标准也已将 RLIMIT_RSS 标记为“obsolete”。你执行 ulimit -m 100000 后,ulimit -m 显示数值可能变化,但进程仍可无约束地增长 RSS,top 或 ps aux --sort=-rss 可验证这一点。
真正有效的替代方案:使用 cgroups v2(推荐)
现代 Linux(内核 ≥ 4.5,默认启用 cgroups v2)应使用 memory.max 进行精确的物理内存(含 page cache、anon memory 等)限制:
- 确认使用 cgroups v2:
mount | grep cgroup应显示type cgroup2 - 为当前 shell 创建并进入内存受限的 scope:
sudo systemd-run --scope -p MemoryMax=512M bash
此命令会启动一个新 bash,其所有子进程均受 512MB 内存上限约束(含 OOM killer 保护) - 验证:
cat /sys/fs/cgroup/system.slice/systemd-run-*.scope/memory.max应输出536870912;运行stress --vm 1 --vm-bytes 600M会被立即 OOM kill
兼容旧系统或手动 cgroups v1 方式(不推荐)
若必须用 cgroups v1(如 CentOS 7 默认):
- 挂载 memory 子系统:
sudo mount -t cgroup -o memory none /sys/fs/cgroup/memory - 创建控制组:
sudo mkdir /sys/fs/cgroup/memory/myshell && echo $$ | sudo tee /sys/fs/cgroup/memory/myshell/cgroup.procs - 设上限(字节):
echo 536870912 | sudo tee /sys/fs/cgroup/memory/myshell/memory.limit_in_bytes - 注意:需 root 权限,且对已运行进程追加限制有延迟,不如 cgroups v2 的
systemd-run干净可靠
补充说明:ulimit 的其他相关项
虽然 -m 失效,但以下仍有效(但非物理内存):
-
ulimit -v(RLIMIT_AS):限制虚拟地址空间大小,可防止 malloc 成功后因缺页分配过多物理内存,有一定间接效果,但易被 mmap/MAP_NORESERVE 绕过 -
ulimit -d:限制数据段(data + brk),对堆影响有限,不控 page cache 或匿名映射 - 这些都不是对 RSS 的硬性实时物理内存锁,仅作辅助参考











