提问人:ABu 提问时间:8/9/2023 最后编辑:ABu 更新时间:8/10/2023 访问量:29
调试会话的长期影响,即使在分离后也是如此 (linux)
Long-term effects of a debugging session, even after detaching (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),可能是由于以下事件序列:
- 该范围可能是指库中包含全局变量的部分。这就是页面被标记为可写(权限 rw-p)的原因。
.bss
- 全局变量可能已被修改,因此映射的页面不再与磁盘中的相应页面匹配。
- 内核在类似写入时复制的策略下分配一个新页面。该页面现在是匿名的,因为它不再与相应的文件支持的页面匹配。
- 如果将来的某个时候有一些页面回收,那么该页面(因为它现在是匿名的)可以被交换掉,而不是像未修改的文件支持的页面那样被丢弃。
还行。如果我将相同的逻辑应用于创建断点的调试器,则在我的脑海中可能会发生以下事件序列:
- 二进制文件的 .text 部分是只读的,但由于断点是通过调用 而创建的,因此在内核模式下执行,因此内核可以修改页面,因为内核绕过权限。
ptrace
- 调试器实际执行的操作是将断点位置的指令替换为陷阱指令,因此包含被替换指令的相应页面已被修改,因此它变得匿名,如上例所示。
ptrace
- 当调试器分离并退出时,如果调试器没有错误,它将删除所有断点,从而还原对文本所做的所有更改。
- 内核不知道页面已恢复到其原始状态(它刚刚见证了一组修改),因此即使在调试器退出后,页面仍保持匿名。
这意味着调试器将导致进程的内存布局发生更改,即使在它退出后也是如此。这意味着,例如,在页面回收的情况下,成为匿名的页面将被交换掉,而不是像在正常情况下那样被丢弃。这会对系统性能造成影响,因为内核必须管理比以前更多的匿名页面的生命周期(特别是如果在调试会话之后,用户创建了大量断点,从而分散到多个页面)
如果我对情况的理解是正确的,那么即使在完成调试会话后,调试器是否也会对性能造成影响?
注意:我对另一个案例感到困惑:
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
该页面是只读的、文件支持的,并且仍然是匿名的。这怎么可能?
答: 暂无答案
评论