我试图了解我的嵌入式Linux应用程序的内存使用情况.该/proc/pid/maps实用程序/文件似乎是看到细节的好资源.不幸的是,我不理解所有列和条目.
/proc/pid/maps实用程序/文件是否有良好的资源/文档?
匿名inode 0条目是什么意思?这些似乎是一些较大的内存段.
Jay*_*rod 245
每行/proc/$PID/maps描述进程或线程中连续虚拟内存的区域.每行都有以下字段:
address perms offset dev inode pathname
08048000-08056000 r-xp 00000000 03:0c 64593 /usr/sbin/gpm
Run Code Online (Sandbox Code Playgroud)
-则会出现a而不是r/ w/ x.如果某个区域未共享,则为私有区域,因此p将显示a而不是s.如果进程尝试以不允许的方式访问内存,则会生成分段错误.可以使用mprotect系统调用更改权限.mmap)映射的,则这是映射开始的文件中的偏移量.如果内存未从文件映射,则它只是0.[heap],[stack]或[vdso].[vdso]代表虚拟动态共享对象.它被系统调用用于切换到内核模式.这是一篇关于它的好文章.你可能会注意到很多匿名区域.这些通常由mmap任何文件创建,但不附加到任何文件.它们用于许多杂项内容,例如共享内存或未在堆上分配的缓冲区.例如,我认为pthread库使用匿名映射区域作为新线程的堆栈.
虽然问题专门提到了嵌入式系统,但标题只提到了proc/<pid>/maps,这对于理解“正常”程序也非常有用。在这个更广泛的上下文中,重要的是要认识到由分配的内存malloc()可以最终位于堆中或任意数量的匿名内存段中。因此,大块匿名内存很可能来自malloc().
更准确地说,as指/proc/<pid>/maps的[heap]是分配给静态变量的内存(称为BSS 段)和称为“程序中断”的地址之间的连续区域(见下图)。最初,该区域是空的并且没有堆。当被调用时,它可以通过系统调用\xe2\x80\x94要求内核\xe2\x80\x94移动程序中断来malloc()创建/扩展堆。brk()同样,free()如果与程序中断相邻的所有地址都不再使用,则可以缩小堆。
malloc()然而,移动程序中断并不是可以为自己腾出更多空间的唯一方法。它还可以通过系统调用\xe2\x80\x94要求内核mmap()\xe2\x80\x94在堆栈和堆之间的某个位置保留一块空间(见下图)。以这种方式分配的内存显示/proc/<pid>/maps为问题中提到的“匿名 inode 0 条目”。
\n图片来源
值得对mmap()系统调用进行一些详细说明。可以创建四种内存映射mmap(),每种内存映射都有不同的用途。首先,内存可以与某个文件的内容绑定,也可以不绑定。后者被称为“匿名”地图。其次,内存可以是“私有”的,也可以是“共享的”。私有意味着一个进程所做的更改对任何其他进程都是不可见的;这通常以一种惰性且高效的方式实现,称为“写时复制”。共享意味着每个进程都可以访问相同的底层物理内存。以下是我所知道的每种内存映射的用途:
malloc()动态库的BSS段,线程的堆栈空间回到/proc/<pid>/maps,您可以通过查看“pathname”和“perms”列来找出每行描述的内存映射类型。(这些列名称来自内核文档)。对于文件映射,“路径名”列将保存正在映射的文件的实际路径。对于匿名地图,“路径名”列将为空。还有一些特殊的路径名,例如[heap]和[stack]。对于私有和共享地图,“perms”列将分别包含p或s标志。
当前malloc()用于brk()小分配和mmap()大分配的实现。在堆上分配少量内存是有意义的,因为通常可以找到必要的空间,而不必进行昂贵的系统调用(例如,通过重用以前释放的空间)。然而,大量分配存在永远不会被释放回操作系统的风险。考虑一下如果您要在堆上进行大量分配,然后进行一堆小分配,会发生什么情况。即使在释放大分配之后,程序中断也无法移回,直到所有小分配也被释放为止。这个简单的示例假设分配按顺序进入堆,这是一种幼稚的方法,但它说明了堆如何使将内存释放回操作系统变得更加困难。
这是相关部分man malloc:
\n\n通常,malloc() 从堆中分配内存,并使用 sbrk(2) 根据需要调整堆的大小。当分配大于 MMAP_THRESHOLD 字节的内存块时,glibc malloc() 实现会使用 mmap(2) 将内存分配为私有匿名映射。MMAP_THRESHOLD 默认情况下为 128 kB,但可以使用 mallopt(3) 进行调整。在 Linux 4.7 之前,使用 mmap(2) 执行的分配不受 RLIMIT_DATA 资源限制的影响;从 Linux 4.7 开始,对于使用 mmap(2) 执行的分配也强制执行此限制。
\n
总之,如果您的程序使用malloc(),则malloc()可能负责许多映射到虚拟内存并由 报告的大型匿名段/proc/<pid>/maps。
买者自负:我在这里写的几乎所有内容都是我今天才学到的,所以请持保留态度。也就是说,我发现以下资源链接对于理解所有这些非常有帮助:
\n/proc,不幸的是我认为没有办法直接链接到相关部分。但如果你搜索“/proc/PID/maps”,你应该能够找到正确的地方。malloc()创建堆?brk()VS的优点mmap()malloc()和free()工作请检查: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
Run Code Online (Sandbox Code Playgroud)
地址字段是映射所占用的过程中的地址空间。
perms字段是一组权限:
r = read
w = write
x = execute
s = shared
p = private (copy on write)
Run Code Online (Sandbox Code Playgroud)
offset字段是文件/其他文件的偏移量;
dev是设备(主要:次要);
inode是该设备上的inode。0表示没有inode与内存区域关联,就像BSS(未初始化的数据)一样。
路径名字段通常将是支持映射的文件。对于ELF文件,您可以通过查看ELF程序标头(readelf -l)中的Offset字段轻松地与offset字段进行协调。
在Linux 2.0下,没有提供路径名的字段。