V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
xing393939
V2EX  ›  Go 编程语言

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

  •  
  •   xing393939 ·
    xing393939 · 2022-06-22 16:16:36 +08:00 · 1285 次点击
    这是一个创建于 903 天前的主题,其中的信息可能已经有所发展或是发生改变。

    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 调用并没有看到这个地址。
    第 1 条附言  ·  2022-06-27 15:28:28 +08:00
    感谢大家的指定,2 点疑惑已经解除:
    1. 地址 7f0b986ef000 处申请了 128k ,紧接着的地址 7f0b9870f000 又申请了 256k ,而在 pmap 的视图上把这 2 块内存合并了
    2. 7f0b71a7e000 的地址,在我加上-f 跟踪子线程后,发现子线程又调用了 mmap ,正好是这个地址
    2 条回复    2022-06-25 19:04:07 +08:00
    beordle
        1
    beordle  
       2022-06-24 23:33:59 +08:00   ❤️ 1
    你没有 -f 跟踪子线程 可以先增加跟踪,看看是不是符合预期。
    katsusan
        2
    katsusan  
       2022-06-25 19:04:07 +08:00   ❤️ 1
    kernel 会对进程的 memory mapping 作 merge,比如你先申请 128K 再申请 256K,如果 128K 后的 gap 里有 256K 空间可用,
    这两块 vma 会被合并在到一起, 在 process mapping 上就体现为一块 384K 的虚拟地址区域.
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4168 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 10:07 · PVG 18:07 · LAX 02:07 · JFK 05:07
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.