查看 Go 内存分配,用 strace 跟踪 mmap 调用的数据和 pmap 看到的内存不一致?

2022-06-22 16:16:36 +08:00
 xing393939

1 ,test 代码见: https://go.dev/play/p/2xa_tqKsjWH

2 ,使用命令 strace -e 'signal=!all' -e '!rt_sigreturn,rt_sigaction,rt_sigprocmask,futex' ./test 得到

execve("./test", ["./test"], 0x7fff95cd9970 /* 21 vars */) = 0
arch_prctl(ARCH_SET_FS, 0x4cba70)       = 0
sched_getaffinity(0, 8192, [0, 1, 2, 3, 4, 5, 6, 7]) = 32
openat(AT_FDCWD, "/sys/kernel/mm/transparent_hugepage/hpage_pmd_size", O_RDONLY) = 3
read(3, "2097152\n", 20)                = 8
close(3)                                = 0
mmap(NULL, 262144, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0b9870f000
mmap(NULL, 131072, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0b986ef000
mmap(NULL, 1048576, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0b985ef000
mmap(NULL, 8388608, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0b97def000
mmap(NULL, 67108864, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0b93def000
mmap(NULL, 536870912, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0b73def000
mmap(0xc000000000, 67108864, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xc000000000
mmap(0xc000000000, 67108864, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xc000000000
mmap(NULL, 33554432, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0b71def000
mmap(NULL, 2165776, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0b71bde000
mmap(0x7f0b986ef000, 131072, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f0b986ef000
mmap(0x7f0b9866f000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f0b9866f000
mmap(0x7f0b981f5000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f0b981f5000
mmap(0x7f0b95e1f000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f0b95e1f000
mmap(0x7f0b83f6f000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f0b83f6f000
mmap(NULL, 1048576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0b71ade000
mmap(NULL, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0b71ace000
mmap(NULL, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0b71abe000
sigaltstack(NULL, {ss_sp=NULL, ss_flags=SS_DISABLE, ss_size=0}) = 0
sigaltstack({ss_sp=0xc000002000, ss_flags=0, ss_size=32768}, NULL) = 0
gettid()                                = 3689
clone(child_stack=0xc000050000, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS, tls=0xc000040090) = 3690
clone(child_stack=0xc000052000, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS, tls=0xc000040490) = 3691
clone(child_stack=0xc00004c000, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS, tls=0xc000040890) = 3693
write(2, "0xc00003c768", 120xc00003c768)            = 12

3 ,使用pmap -p 3689得到

0000000000400000    380K r-x-- /root/logs/test
000000000045f000    420K r---- /root/logs/test
00000000004c8000     16K rw--- /root/logs/test
00000000004cc000    200K rw---   [ anon ]
000000c000000000  65536K rw---   [ anon ]
00007f0b71a7e000  36292K rw---   [ anon ]
00007f0b73def000 263680K -----   [ anon ]
00007f0b83f6f000      4K rw---   [ anon ]
00007f0b83f70000 293564K -----   [ anon ]
00007f0b95e1f000      4K rw---   [ anon ]
00007f0b95e20000  36692K -----   [ anon ]
00007f0b981f5000      4K rw---   [ anon ]
00007f0b981f6000   4580K -----   [ anon ]
00007f0b9866f000      4K rw---   [ anon ]
00007f0b98670000    508K -----   [ anon ]
00007f0b986ef000    384K rw---   [ anon ]
00007ffdc654c000    132K rw---   [ stack ]
00007ffdc65a0000     12K r----   [ anon ]
00007ffdc65a3000      8K r-x--   [ anon ]

我发现 2 个令人疑惑的地方,希望有大佬能指点:

  1. 地址 7f0b986ef000 处,mmap 调用明明只申请了 128K 内存,怎么 pmap 命令却显示此处有 384K 内存。
  2. pmap 显示地址 7f0b71a7e000 处的内存有 36292K ,这个内存地址是如何产生的? starce 跟踪到的 mmap 调用并没有看到这个地址。
1148 次点击
所在节点    Go 编程语言
2 条回复
beordle
2022-06-24 23:33:59 +08:00
你没有 -f 跟踪子线程 可以先增加跟踪,看看是不是符合预期。
katsusan
2022-06-25 19:04:07 +08:00
kernel 会对进程的 memory mapping 作 merge,比如你先申请 128K 再申请 256K,如果 128K 后的 gap 里有 256K 空间可用,
这两块 vma 会被合并在到一起, 在 process mapping 上就体现为一块 384K 的虚拟地址区域.

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/861411

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX