mlockall 会立即锁定当前及未来所有内存页,需 CAP_IPC_LOCK 权限和非零 ulimit -l,应使用 MCL_CURRENT | MCL_FUTURE 标志组合,失败时需按 errno 区分处理。

mlockall 会立即锁定所有当前和未来分配的内存页
调用 mlockall 后,进程的全部虚拟内存(包括已分配的堆、栈、数据段,以及后续通过 malloc、mmap 等分配的内存)都会被锁定在物理内存中,不会被内核 Swap 到磁盘。但前提是进程有足够权限——普通用户默认无权执行该系统调用。
必须以 CAP_IPC_LOCK 权限运行或用 root 启动
Linux 下 mlockall 需要 CAP_IPC_LOCK 能力,否则会返回 EPERM 错误。常见做法有:
- 用
sudo启动程序(简单但不推荐用于生产) - 给二进制文件授予权限:
sudo setcap cap_ipc_lock+ep ./myapp - 在容器中启动时加
--cap-add=IPC_LOCK - 确认 ulimit -l 不为 0(
ulimit -l 65536可设为 64MB;值为 0 表示禁止锁定)
调用后需检查返回值并处理 MCL_FUTURE / MCL_CURRENT 标志
mlockall 接收两个常用标志组合:
-
MCL_CURRENT:锁定当前已映射的所有内存页(如全局变量、栈、已分配的堆) -
MCL_FUTURE:锁定此后所有新分配的内存页(关键!漏掉这个就白锁了) - 通常应一起使用:
mlockall(MCL_CURRENT | MCL_FUTURE) - 失败时返回 -1,
errno可能是ENOMEM(物理内存不足)、EPERM(权限不足)或EAGAIN(超出RLIMIT_MEMLOCK限制)
示例片段:
立即学习“C++免费学习笔记(深入)”;
#include <sys/mman.h>
#include <errno.h>
#include <stdio.h>
if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {
perror("mlockall");
// 检查 errno 是 EPERM 还是 ENOMEM,决定是改权限还是降内存需求
}
解锁要用 munlockall,且注意大页内存与透明大页的影响
munlockall() 可释放全部锁定,但它不保证立即生效——内核可能延迟回收页框。更关键的是:
- 如果启用了透明大页(THP),
mlockall仍可工作,但首次分配大页时可能触发短暂阻塞 - 显式使用
mmap(..., MAP_HUGETLB)分配的大页默认已锁定,无需再mlockall - 锁定过多内存会导致其他进程 OOM,或触发内核警告(dmesg 中可见 "mlock limit exceeded")
- 调试时可用
cat /proc/<pid>/status | grep -i lock</pid>查看MMUPageSize和MMUPageCount是否增长
真正难搞的不是调用本身,而是锁内存后暴露的隐性问题:比如本该被换出的调试符号页全留在 RAM 里,导致 RSS 突增;或者因锁定失败未降级处理,直接 crash。


















