什么是 mlock
mlock()/mlockall() 把指定内存页锁定在物理内存中,禁止内核换出到 swap,从而保证访问延迟可预测:实时计算、音频处理、数据库的共享缓冲、加密密钥常这么做。代价是这部分内存不可回收,锁定过多会挤压系统可用内存。普通用户受 RLIMIT_MEMLOCK 限制,服务通过 systemd 的 LimitMEMLOCK 单独放开比改全局 limits.conf 更收敛。
基本信息
| 接口 | mlock(2) / mlockall(2),配套 munlock/munlockall |
|---|---|
| 限制项 | RLIMIT_MEMLOCK(ulimit -l) |
| 放宽方式 | systemd: LimitMEMLOCK=infinity |
| 绕过方式 | CAP_IPC_LOCK 能力 |
| 观测 | grep Locked /proc/meminfo,或 /proc/<pid>/status 的 VmLck |
典型使用场景
- 实时业务:需要避免换页抖动带来的尾延迟,把关键缓冲区锁定
- 数据库与缓存服务:把共享缓冲池锁定,防止突发使用触发换页
- 安全敏感进程:密钥与凭据锁定后降低被换出到磁盘的风险
- 对内存限制敏感的服务排障:报 Cannot allocate memory 时确认是否卡在 memlock 限制上
- 容器与微服务:在 compose/systemd 里给单个服务放宽,而不是全局放开
查看与放行
查看与放行
ulimit -l # 当前会话的 memlock 限额(KB)
grep -i locked /proc/meminfo # 系统已锁定内存总量
grep VmLck /proc/<pid>/status # 单进程锁定字节数
systemctl show myservice -p LimitMEMLOCK # 服务级限额
# 服务单元里放行:LimitMEMLOCK=infinity 后 systemctl daemon-reload && restart常见取值与含义
| 取值 | 含义 | 注意 |
|---|---|---|
| 64KB 量级 | 默认软/硬限制,很多发行版就是这么小 | 单进程锁不了多少内存 |
| unlimited | 服务已显式放开 | 要核算所有实例的锁定总量 |
| VmLck 持续增长 | 进程不断加锁 | 结合业务确认是有意行为还是泄漏 |
| Locked 接近物理内存 | 系统几乎无可回收余量 | OOM 风险显著上升 |
limits.conf 的 memlock 只对新登录会话生效,已经在跑的服务必须重启才能拿到新限额。
锁定内存不可回收:风控、缓存类服务盲目 mlockall 会让系统在内存紧张时失去缓冲空间,直接放大 OOM 概率。
容器里 ulimit -l 的数值由运行时下发:Docker 用 --ulimit memlock=-1 放宽,Kubernetes 需通过 securityContext 或运行时配置调整,在宿主侧改 limits.conf 不会自动传到容器里。
评估锁定量时按“单进程上限 × 实例数”估算并留出系统余量:把每个实例的限额简单相加,结果往往已经超过物理内存,纸面上算清再放行。