Linux 内核把物理内存分为了两部分:
一部分是映射至文件的(有文件背景的),一部分是没有映射至文件的,即匿名内存,它们和共不共享没有关系!

什么是匿名内存?匿名内存就是没有文件背景的内存,就是无法和磁盘进行交换的,比如堆栈。

进程通过如下方式占用的物理内存,计入 file_rss,也就是 top 的 SHR 字段。

  • 程序的代码段。
  • 动态库的代码段。
  • 通过 mmap 做的文件映射。
  • 通过 mmap 做的匿名映射,但指明了MAP_SHARED属性。
  • 通过 shmget 申请的共享内存。

我们看到一般这些内存都是以共享方式存在。

下面是 top 命令的输出片断:

   PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                             
  4982 oracle    20   0  837932 115328 113312 S   0.0  6.2   0:01.09 oracle                                   

top 命令通过解析 /proc/<pid>/statm 统计 VIRT、RES 和 SHR 字段值:

# cat /proc/4982/statm 
209483 28832 28328 47296 0 965 0

209483*4=837932,即 VIRT,进程虚存的总大小,即进程申请的内存大小。
28832*4=115328,即 RES,即平常我们说的常驻内存,是进程真正使用的内存量。
28328*4=113312,即 SHR,即平常我们说的共享内存,上面已经描述过哪些内存会被计入共享内存。

新 fork 之后的子进程,由于 copy on write 机制,在页面被修改之前,和父进程共享。这部分值并不体现在 top 命令的 SHR 字段内。
所以 top 命令的 SHR 并不是准确描述了进程与其他进程共享使用的内存数量,是存在误差的。

如何获取准确获取进程的共享内存量和独占内存量呢?

共享内存量:

# grep Shared_ /proc/4982/smaps | awk 'BEGIN {sum=0} {sum+=$2} END {print sum}'
61360

独占内存量:

# grep Private_ /proc/4982/smaps | awk 'BEGIN {sum=0} {sum+=$2} END {print sum}'
54096

这两个值加起来为 115456,跟上面的 RES 大致相当。

-- By 许望(RHCA、OCM、VCP)
最后修改:2020 年 04 月 29 日 02 : 42 PM
如果觉得我的文章对你有用,请随意赞赏