Linux调试会话分离后的长期影响及内存相关疑问
动态库与调试器场景下的内存匿名页分析
先从动态加载库开始分析。在smaps输出中,常能看到指向.so文件的可写段被标记为匿名,例如:
7fa9942af000-7fa9942f1000 rw-p 03d98000 fd:0c 131627 /usr/share/oracle/19.0.0/client_1/lib/libclntsh.so.19.1 Size: 264 kB KernelPageSize: 4 kB MMUPageSize: 4 kB Rss: 4 kB Pss: 4 kB Shared_Clean: 0 kB Shared_Dirty: 0 kB Private_Clean: 0 kB Private_Dirty: 4 kB Referenced: 4 kB Anonymous: 4 kB LazyFree: 0 kB AnonHugePages: 0 kB ShmemPmdMapped: 0 kB FilePmdMapped: 0 kB Shared_Hugetlb: 0 kB Private_Hugetlb: 0 kB Swap: 188 kB SwapPss: 188 kB Locked: 0 kB THPeligible: 0 ProtectionKey: 0 VmFlags: rd wr mr mw me ac sd
该地址范围里的4kB匿名页,产生过程大致如下:
- 此范围对应库的.bss段(包含全局变量),因此权限为rw-p;
- 全局变量被修改后,内存页与磁盘中的对应页内容不再匹配;
- 内核通过写时复制机制分配新页,该页因与原文件页内容不一致,被标记为匿名;
- 后续页回收时,这个匿名页会被换出到交换分区,而非直接丢弃。
将这一逻辑延伸到调试器断点场景,可推测出如下过程:
- 二进制的.text段为只读,但调试器可通过内核态的
ptrace调用绕过权限限制修改页面; - 调试器通过
ptrace将断点处的指令替换为陷阱指令,被修改的页面因此变为匿名; - 若调试器无bug,在分离退出前会移除断点,恢复.text段的原始内容;
- 但内核并不知晓页面已恢复原样,仍将其标记为匿名。
这意味着调试器退出后,进程的内存布局仍会被改变:页回收时这些匿名页会被换出而非丢弃,若设置的断点较多,会增加内核对匿名页的管理负担,进而影响性能。
若上述理解正确,调试会话结束后是否真的会产生性能影响?
注: 还有一个案例令人困惑:
7fa994544000-7fa994545000 r--p 0002c000 103:04 10234 /usr/lib64/ld-2.28.so Size: 4 kB KernelPageSize: 4 kB MMUPageSize: 4 kB Rss: 4 kB Pss: 4 kB Shared_Clean: 0 kB Shared_Dirty: 0 kB Private_Clean: 0 kB Private_Dirty: 4 kB Referenced: 4 kB Anonymous: 4 kB LazyFree: 0 kB AnonHugePages: 0 kB ShmemPmdMapped: 0 kB FilePmdMapped: 0 kB Shared_Hugetlb: 0 kB Private_Hugetlb: 0 kB Swap: 0 kB SwapPss: 0 kB Locked: 0 kB THPeligible: 0 ProtectionKey: 0 VmFlags: rd mr mw me dw ac sd
这个页面是只读的文件映射页,却被标记为匿名,这是如何实现的?
内容的提问来源于stack exchange,提问作者ABu
相关产品推荐
相关产品推荐

