调用munmap()后页面回收仍存在的原因排查
排查自定义malloc/free实现中munmap后Minor Page Faults未恢复的问题
针对你用mmap()/munmap()重实现malloc/free后,/usr/bin/time -v显示Minor Page Faults在free后无法恢复到初始值的问题,给几个具体排查方向:
1. 验证内存释放核心逻辑的正确性
- 检查链表操作是否存在残留引用:在
__free_page中修改prev/next指针后,是否还有其他结构体持有该page的指针?比如binder的pages链表有没有彻底移除当前page?若存在残留引用,内核可能不会彻底回收对应页面的统计信息。 - 确认munmap参数与mmap完全匹配:
- 确保
page->size的值和mmap()调用时传入的size完全一致,分配后没有被任何逻辑修改过(比如是否有代码调整过page->size)。如果munmap()的大小小于实际映射内存,内核只会释放部分页面,剩余页面仍会被统计。 - 检查
munmap()的起始地址是否和mmap()返回的地址完全相同:t_page *page直接接收mmap返回值,有没有因类型转换、指针偏移导致地址错误?比如初始化时是否不小心修改了page指针的位置?
- 确保
2. 排查测试程序与运行环境问题
- 确保测试程序无野指针访问:如果测试代码在
free()后存在对已释放内存的访问(哪怕只是打印指针地址,某些编译器优化或系统机制可能误判),会导致内核重新加载页面,Minor Page Faults不会下降。务必保证测试流程是纯粹的malloc→free,无后续内存访问操作。 - 验证符号覆盖是否完全:用
LD_PRELOAD加载自定义动态库时,确认所有malloc/free调用都走你的实现:- 用
nm -D libmalloc.so检查是否正确导出了malloc和free符号; - 用
ltrace ./test_program跟踪系统调用,确认所有内存分配/释放调用都指向你的动态库,而非libc的实现。若存在混合调用(比如标准库内部的隐式malloc),会导致统计数据失真。
- 用
3. 检查page结构体的初始化与定义
- 确认
t_page结构体初始化完全正确:ft_bzero(page, sizeof(t_page))是否覆盖了整个结构体?如果sizeof(t_page)计算错误(比如结构体成员对齐问题、遗漏成员),会导致page->size等关键字段未被正确初始化,进而导致munmap()用错参数。 - 检查
t_page的size字段是否在__alloc_page中被正确赋值为mmap的size参数,有没有被后续逻辑意外修改。
4. 排查内核层面的内存统计延迟
虽然你的实现只用mmap/munmap,但部分场景下内核会延迟回收页面的统计信息。你可以尝试在free后调用sleep(1)再退出测试程序,观察Minor Page Faults是否有变化,排除统计延迟的影响。
内容的提问来源于stack exchange,提问作者lucocozz
相关产品推荐
相关产品推荐

