mlock()可将内存页锁定在RAM中防止交换,适用于加密、实时音视频等低延迟场景,但需root权限或CAP_IPC_LOCK能力,且受RLIMIT_MEMLOCK限制。

在Linux中,mlock() 系统调用可将进程的指定内存页锁定在物理RAM中,避免被内核交换(swap)到磁盘。这适用于对延迟敏感、需保证内存常驻的场景(如加密密钥处理、实时音视频缓冲、金融交易逻辑等),但需谨慎使用——过度锁定会挤占系统可用内存,影响整体稳定性。
前提条件与权限要求
普通用户默认无权锁定内存,需满足以下任一条件:
- 进程以 root 权限运行
- 用户被赋予 CAP_IPC_LOCK 能力(例如通过
setcap cap_ipc_lock+ep ./myapp) - 系统放宽限制:修改
/proc/sys/vm/mlockable(较新内核)或调整RLIMIT_MEMLOCK限制(传统方式)
常用锁定方式
实际开发中主要通过以下接口操作:
-
mlock(const void *addr, size_t len):锁定从addr开始的len字节内存(地址需页对齐) -
mlockall(int flags):一次性锁定整个进程的多种内存区域,常用标志包括:
•MCL_CURRENT(已分配的堆、栈、数据段)
•MCL_FUTURE(后续新分配的内存也自动锁定) -
munlock()/munlockall():显式解除锁定,释放内存可被交换
关键注意事项
忽略这些细节易导致失败或隐患:
- 锁定地址必须是页对齐的(通常用
sysconf(_SC_PAGESIZE)获取页大小,并对齐指针) - 单次
mlock()最大可锁大小受RLIMIT_MEMLOCK限制(可用ulimit -l查看,单位KB;root默认通常为64KB,可调高) - 锁定后若物理内存不足,后续内存分配(如
malloc())可能失败,需检查返回值并妥善处理 -
mlockall(MCL_FUTURE)不影响已mmap(MAP_ANONYMOUS)分配但未访问的页——首次访问仍可能触发缺页中断并被换出,建议配合madvise(..., MADV_DONTFORK | MADV_DONTDUMP)增强控制
简单验证示例
编译运行以下代码后,可用 cat /proc/$(pidof a.out)/status | grep ^MMU 或观察 /proc/*/smaps 中 Locked: 字段确认是否生效:
#include <sys/mman.h>
#include <unistd.h>
#include <stdio.h>
int main() {
size_t page_size = sysconf(_SC_PAGESIZE);
char *p = malloc(page_size);
if (!p) return 1;
if (mlock(p, page_size) == 0) {
printf("Memory locked successfully\n");
// ... use p
munlock(p, page_size); // 解锁
}
free(p);
return 0;
}










