/proc/pid/maps 地址(并​​转换它们)

pno*_*en2 5 linux memory proc

查看 /proc/pid/maps 中的内存映射时,我们可以看到不同长度的地址:

00400000-0042e000 r-xp 00000000 fb:01 268953                             /bin/nano
0062e000-0062f000 r--p 0002e000 fb:01 268953                             /bin/nano
0062f000-00630000 rw-p 0002f000 fb:01 268953                             /bin/nano
0081e000-00906000 rw-p 00000000 00:00 0                                  [heap]
7f8313e5c000-7f8314109000 rw-p 00000000 fb:01 2399989                    /usr/share/misc/magic.mgc
7f8314109000-7f83142ce000 r--p 00000000 fb:01 2759354                    /usr/lib64/locale/locale-archive
7f83142ce000-7f83142d1000 r-xp 00000000 fb:01 1457046                    /lib64/libdl-2.17.so
7f83142d1000-7f83144d0000 ---p 00003000 fb:01 1457046                    /lib64/libdl-2.17.so
Run Code Online (Sandbox Code Playgroud)

我们有 8 位长度的地址,例如:

  • 00400000-0042e000

还有 12 位长度的(最后 3 位总是 0):

  • 7f8313e5c000-7f8314109000

为什么这些地址的格式是这样的,我可以将它们转换为 8 位长度吗?

小智 9

首先,您不能将地址转换为只有 8 位数字。内存地址可以并且将具有比仅用 8 位数字表示的值大得多的值。

内存地址按/proc/pid/maps原样表示的原因在最近的内核源代码树中的第 283 行fs/proc/task_mmu.c(或task_nommu.c):

283         seq_printf(m, "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu ",
284                         start,
285                         end,
286                         flags & VM_READ ? 'r' : '-',
287                         flags & VM_WRITE ? 'w' : '-',
288                         flags & VM_EXEC ? 'x' : '-',
289                         flags & VM_MAYSHARE ? 's' : 'p',
290                         pgoff,
291                         MAJOR(dev), MINOR(dev), ino);
Run Code Online (Sandbox Code Playgroud)

这归结为在任何具有短于 8 位的十六进制字符串表示的内存地址中,都将填充前导零。任何大于该值的值都将按原样表示,不会被截断为 8 位数字。这就是printk()printf 样式格式的工作方式。

现在该怎么做呢?也许您应该花一点时间思考为什么要将内存地址截断为 8 位数字。你认为这样做有什么好处?

  • 此外,值得一提的是,尾随零会脱落,因为内存不是按字节分配的,但只能按整个页面分配,(在“x86_64”上)通常为 4kiB(因此最后三个十六进制数字将始终为`000`,但很重要)。 (2认同)