Linux匿名mmap区域页面回收机制及手动管理页表相关问题
Linux内核匿名mmap页面回收相关问题解答
一、匿名mmap区域的页面回收流程
- 匿名页没有对应磁盘文件,回收前必须先写入交换分区(swap),生成swap entry并更新页表,标记为swap-backed(不再指向物理页)
- 内核的页回收扫描器(kswapd后台进程或直接回收路径)会遍历匿名页所在的LRU链表,判断页是否可回收:
- 若页是干净的(未被修改),直接释放物理页,更新页表为缺页状态
- 若页是脏的,先触发写回swap,完成后释放物理页并更新页表
- 回收过程中会检查页的引用计数、是否被锁定(如
mlock标记),锁定的页不会被回收
二、手动管理页表的NORESERVE匿名mmap物理页回收问题
如果手动管理该区域的页表(绕过内核默认逻辑),物理页是否会被回收取决于你的操作:
- 若你分配的物理页未关联内核匿名页元数据(
struct page),也未加入内核LRU链表,内核页回收器无法识别这些页,不会主动回收 - 若物理页是通过内核合法接口(如
alloc_page)分配,且映射到用户空间后未从LRU链表移除,内存压力高时内核会尝试回收,但因这类页没有swap backing(你绕过了内核匿名页管理),内核无法将其写入swap,会判定为不可回收,最终不会被驱逐 MAP_NORESERVE标志仅控制是否预留swap空间,不改变内核对已分配物理页的回收判定逻辑,核心是看页是否被内核回收机制纳入管理
三、匿名mmap区域的页面驱逐策略
匿名页驱逐以LRU(最近最少使用)算法为核心,结合以下规则:
- 内核维护活跃(active)和非活跃(inactive)两个LRU链表,通过
page_referenced函数判断页的访问频率,将长时间未被访问的页从active链表移到inactive链表 - 优先驱逐inactive链表中的页,脏页必须先写回swap才能被释放
- 大页面(hugepage)匿名页的驱逐逻辑类似,但会考虑大页面的分配成本,调整驱逐阈值
- 若开启透明大页(THP),匿名页回收会额外处理THP的拆分或整体驱逐逻辑
- 被
mlock锁定的匿名页会被移出LRU链表,不会被驱逐
四、相关代码位置
- 匿名页回收核心逻辑:
mm/vmscan.c,其中shrink_inactive_list负责非活跃链表的页回收,swap_out处理匿名页写入swap的逻辑 - 匿名页LRU管理:
mm/swap.c、mm/vmscan.c,add_to_lru_list、del_from_lru_list等函数负责页在LRU链表的移入移出 - 页引用计数与活跃性判断:
mm/rmap.c中的page_referenced_one、page_referenced函数 MAP_NORESERVE标志处理:mm/mmap.c中的do_mmap函数,创建匿名映射时控制swap空间预留
内容的提问来源于stack exchange,提问作者ONE NO
相关产品推荐
相关产品推荐

