了解 Linux /proc/pid/maps 或 /proc/self/maps
Posted
技术标签:
【中文标题】了解 Linux /proc/pid/maps 或 /proc/self/maps【英文标题】:Understanding Linux /proc/pid/maps or /proc/self/maps 【发布时间】:2010-11-26 22:42:19 【问题描述】:我正在尝试了解我的嵌入式 Linux 应用程序的内存使用情况。 /proc/pid/maps
实用程序/文件似乎是查看详细信息的好资源。不幸的是,我不理解所有的列和条目。
匿名inode 0 条目是什么意思?这些似乎是一些较大的内存段。
【问题讨论】:
proc(5)
mmap(2)
"了解 Linux 内核" 9.3。记忆区; 16.2.内存映射《理解Linux虚拟内存管理器》4.4内存区域
【参考方案1】:
/proc/$PID/maps
中的每一行都描述了进程或线程中的一个连续虚拟内存区域。每行包含以下字段:
address perms offset dev inode pathname
08048000-08056000 r-xp 00000000 03:0c 64593 /usr/sbin/gpm
address - 这是该区域在进程地址空间中的起始地址和结束地址
权限 - 这描述了如何访问该区域中的页面。有四种不同的权限:读、写、执行和共享。如果读/写/执行被禁用,将出现-
而不是r
/w
/x
。如果一个区域不是共享,它是私有,所以p
将出现而不是s
。如果进程试图以不允许的方式访问内存,则会产生分段错误。可以使用mprotect
系统调用更改权限。
offset - 如果区域是从文件映射的(使用mmap
),则这是映射开始的文件中的偏移量。如果内存不是从文件映射的,则它只是 0。
设备 - 如果该区域是从文件映射的,则这是文件所在的主要和次要设备号(十六进制)。
inode - 如果该区域是从文件映射的,则这是文件编号。
路径名 - 如果该区域是从文件映射的,则这是文件的名称。对于匿名映射区域,此字段为空白。还有一些特殊区域的名称如[heap]
、[stack]
或[vdso]
。 [vdso]
代表虚拟动态共享对象。系统调用使用它来切换到内核模式。 Here's a good article about it: "What is linux-gate.so.1?"
您可能会注意到很多匿名区域。这些通常由mmap
创建,但不附加到任何文件。它们用于许多杂项,例如未在堆上分配的共享内存或缓冲区。例如,我认为 pthread 库使用匿名映射区域作为新线程的堆栈。
【讨论】:
是的,pthreads 正在为堆栈分配 8Mb 块,其中较小的部分用于堆栈溢出检测(我认为)。因此,默认情况下,创建的每个 pthread 都会分配一个 8Mb 的 inode 0 内存区域和一个 4Kb 的 inode 0 区域。 所以在您的示例中,gpm
是从一开始就将二进制文件映射到某个虚拟地址,并带有 ELF 标头等?加载器不应该解析 ELF 标头并映射各个部分,而不是整个文件吗?【参考方案2】:
请查看:http://man7.org/linux/man-pages/man5/proc.5.html
address perms offset dev inode pathname
00400000-00452000 r-xp 00000000 08:02 173521 /usr/bin/dbus-daemon
地址域是进程中的地址空间 映射占据。
perms 字段是一组权限:
r = read
w = write
x = execute
s = shared
p = private (copy on write)
offset 字段是文件的偏移量/其他;
dev 是设备(主要:次要);
inode 是该设备上的 inode。0 表示没有 inode 与 memoryregion 相关联,就像 BSS(未初始化数据)一样。
路径名字段通常是支持的文件 映射。对于 ELF 文件,您可以轻松地与 通过查看 ELF 中的偏移字段来获取偏移字段 程序头文件(readelf -l)。
在 Linux 2.0 下,没有给出路径名的字段。
【讨论】:
【参考方案3】:内存映射不仅用于将文件映射到内存中,而且还是一种向内核请求 RAM 的工具。这些是那些 inode 0 条目 - 你的堆栈、堆、bss 段等等
【讨论】:
以上是关于了解 Linux /proc/pid/maps 或 /proc/self/maps的主要内容,如果未能解决你的问题,请参考以下文章
为啥我可以在 /proc/pid/maps 输出中看到几个相同的段?