内存锁定系统调用:mlock, mlock2, munlock, mlockall, munlockall详解
Linux操作系统提供了一组内存锁定系统调用,允许进程将其部分或全部地址空间锁定在物理内存中,防止这些内存页被换出到交换空间。这对于实时应用程序、安全敏感的程序以及需要确保内存访问延迟可预测的场景非常重要。本文将详细介绍这些系统调用的功能、用法和工作原理。
内存锁定的基本概念
内存锁定机制允许程序锁住其部分或全部地址空间,确保这些内存页始终驻留在物理内存中。这意味着无论系统内存压力如何,操作系统不会将这些内存页换出到交换空间(swap space)[9]。这对于以下场景特别有价值:
实时应用程序:需要确保内存访问的时间延迟可预测
安全敏感应用:防止敏感数据被写入交换文件,避免程序结束后可能被恢复
高性能计算:确保关键数据结构始终在内存中,减少访问延迟
需要注意的是,内存锁定和解锁都是以整页为单位进行的,在x86 Linux系统上,页面大小通常为4KB[9]。
mlock() 和 munlock() 函数
mlock() 函数
mlock()系统调用允许进程锁定指定范围的地址空间:
int mlock(const void *addr, size_t len);
参数说明:
addr:指定要锁定的地址范围的起始地址
len:指定要锁定的地址空间长度(以字节为单位)
调用成功时返回0,失败时返回-1并设置errno[1][2]。
mlock()锁定从addr开始、长度为len字节的地址范围内的所有页面。包含指定地址范围的所有页面在调用成功返回时都保证驻留在RAM中,并且会一直保持在RAM中,直到被解锁[2]。
munlock() 函数
munlock()系统调用用于解锁之前通过mlock()锁定的内存:
int munlock(const void *addr, size_t len);
参数与mlock()相同,用于指定要解锁的内存区域。调用成功后,指定范围内的所有页面可以被操作系统根据需要再次换出到交换空间[2]。
mlock2() 函数
mlock2()是mlock()的扩展版本,增加了更多的控制选项:
int mlock2(const void *addr, size_t len, unsigned int flags);
除了前两个与mlock()相同的参数外,它增加了flags参数:
如果flags为0,则mlock2()的行为与mlock()完全相同
如果flags为MLOCK_ONFAULT,则只锁定当前已在内存中的页面,并标记整个范围,使得剩余的非驻留页面在发生页面错误时才被锁定[5][7]
MLOCK_ONFAULT标志提供了更高效的内存锁定方式,特别适用于处理大型内存映射的应用程序,其中只有部分数据需要被访问[10][13]。这种方式可以显著减少内存使用,因为只有实际访问的页面才会被锁定。
mlockall() 和 munlockall() 函数
mlockall() 函数
mlockall()系统调用锁定调用进程的整个地址空间:
int mlockall(