http://yalung929.blog.163.com/blog/static/203898225201212981731971/

http://www.fuzhijie.me/?p=741

引 言: top命令作为Linux下最常用的性能分析工具之一,可以监控、收集进程的CPU、IO、内存使用情况。比如我们可以通过top命令获得一个进程使用了多少虚拟内存(VIRT)、物理内存(RES)、共享内存(SHR)。

最近遇到一个咨询问题,某产品做性能分析需要获取进程占用物理内存的实际大小(不包括和其他进程共享的部分),看似很简单的问题,但经过研究分析后,发现背后有很多故事……

1 VIRT RES SHR的准确含义

三个内存指标,VRIT,RES,SHR准确含义是什么?谁能告诉我们?MAN页?Linux专家?SUSE工程师?Linus?谁能说出最正确答案?没人!因为惟有源代码才是最正确的答案。

那我们就去看下源码吧,这就是开源软件的最大的好处。

首先这三个数据的源头,肯定是内核,进程的相关数据结构肯定是由内核维护。那么top作为一个用户空间的程序,要想获取内核空间的数据,就需要通过系统接口(API)获取。而proc文件系统是Linux内核空间和用户空间交换数据的一个途径,而且是非常重要的一种途径,这点和windows更倾向于基于函数调用的形式不同。

当你调用系统函数read读取一个普通文件时,内核执行对应文件系统的代码从磁盘传送文件内容给你。

当你调用系统函数read读取一个 proc文件时,内核执行对应的proc文件系统的代码从内核的数据结构中传送相关内容给你。proc文件和磁盘没有关系。只是系统接口而已。

而一个进程的相关信息,Linux全部通过/proc/<pid>/内的文件告诉了我们。

如下,你可以使用普通的文件读写工具,比如cat获取进程的各种信息。这比函数调用的方式灵活多了、丰富多了。

回到我们的问题,top命令显示的进程信息,肯定也是通过proc获取的,因为除此之外没有其他途径,没有系统函数可以做这个事情,top也不可能越过用户层直取内核获取数据。

带着以上信息,很快就可以从top的源码中找到关键代码:

啊哈,statm文件:

根据sscanf的顺序,第一个值是VIRT,第二个值是RES,第三个值是SHR!

等等,好像数值对不上,top显示的SHR是344k,而statm给出的是86!

再来看一行关键代码:

statm显示的是页数,top显示的是KB。X86下,一页是4KB,86 * 4 = 344。这就对了!

于是乎,我们找到了最关键的入口,接下来按图索骥,看看内核是怎么产生statm文件内容就可以了。~~

proc_pid_statm函数负责产生statm文件内容,当你使用cat命令打印statm文件时,内核中的这个函数会执行。

proc_pid_statm获取进程的mm_struct数据结构,而这个数据结构就是进程的内存描述符,通过它可以获取进程内存使用、映射的全部信息。

进一步考察task_statm函数,可以看到:

第一个值(VIRT)就是mm->total_vm,即进程虚存的总大小,这个比较清晰,只要进程申请了内存,无论是malloc还是堆栈还是全局,都会计入这个值;

第二个值(RES)是mm->file_rss+mm->anon_rss;

第三个值(SHR)是mm->file_rss。

RES要和SHR结合者看,内核把物理内存分为了两部分,一部分是映射至文件的,一部分是没有映射至文件的即匿名内存,完全和共不共享没有关系!

但file_rss为什么叫做shared呢?应该是一种指示性表述,表示这部分内存可能是共享的。但并不代表真正共享了。那么到底哪些计入file_rss?通过查阅相关代码,发现(可能有遗漏):

l 程序的代码段。

l 动态库的代码段。

l 通过mmap做的文件映射。

l 通过mmap做的匿名映射,但指明了MAP_SHARED属性。

l 通过shmget申请的共享内存。

即进程通过以上方式占用的物理内存,计入file_rss,也就是top的SHR字段。我们看到一般这些内存都是以共享方式存在。但如果某个动态库只一个进程在使用,它的代码段就没有被共享着。

反过来再来看anon_rss统计的内容,是否就一定是独占的?也不是,比如新fork之后的子进程,由于copy on write机制,在页面被修改之前,和父进程共享。这部分值并不体现在top命令的SHR字段内。

综上所述top命令显示的SHR字段,并不是准确描述了进程与其他进程共享使用的内存数量,是存在误差的。

那么如何获取进程准确的共享内存数量?

2 获取进程准确的共享内存数量

我们注意到在描述进程信息的proc/<pid>内,有一个smaps文件,里面展示了所有内存段的信息,其中有Shared_Clean Shared_Dirty Private_Clean Private_Dirty:几个字段。

找到相关代码,可以看到,一个页面如果映射数>=2计入Shared_* ; 如果=1计入Private_*。(脏页计入*_Dirty,否则计入*_Clean)

统计smaps文件内所有段的Shared_*值的总和就是进程准确的共享内存数量!

统计smaps文件内所有段的Private_*值的总和就是进程准确的独占内存数量!

3 总结

通过以上分析,我们可以得到如下结论:

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

l VIRT是申请的虚拟内存总量。

l RES是进程使用的物理内存总和。

l SHR是RES中”映射至文件”的物理内存总和。包括:

程序的代码段。

动态库的代码段。

通过mmap做的文件映射。

通过mmap做的匿名映射,但指明了MAP_SHARED属性。

通过shmget申请的共享内存。

l /proc/<pid>/smaps内Shared_*统计的是RES中映射数量>=2的物理内存。

l /proc/<pid>/smaps内Private_*统计的是RES中映射数量=1的物理内存。

 
 

剖析top命令显示的VIRT RES SHR值的更多相关文章

  1. 转 linux进程内存到底怎么看 剖析top命令显示的VIRT RES SHR值

    引 言: top命令作为Linux下最常用的性能分析工具之一,可以监控.收集进程的CPU.IO.内存使用情况.比如我们可以通过top命令获得一个进程使用了多少虚拟内存(VIRT).物理内存(RES). ...

  2. linux进程内存到底怎么看 剖析top命令显示的VIRT RES SHR值

    引 言: top命令作为Linux下最常用的性能分析工具之一,可以监控.收集进程的CPU.IO.内存使用情况.比如我们可以通过top命令获得一个进程使用了多少虚拟内存(VIRT).物理内存(RES). ...

  3. linux ps top 命令 VSZ,RSS,TTY,STAT, VIRT,RES,SHR,DATA的含义【转】

    转自:http://blog.csdn.net/zjc156m/article/details/38920321 http://javawind.net/p131 VIRT:virtual memor ...

  4. linux ps top 命令 VSZ,RSS,TTY,STAT, VIRT,RES,SHR,DATA的含义

    VIRT:virtual memory usage 虚拟内存1.进程“需要的”虚拟内存大小,包括进程使用的库.代码.数据等2.假如进程申请100m的内存,但实际只使用了10m,那么它会增长100m,而 ...

  5. linux top命令VIRT,RES,SHR,DATA的含义(转)

    linux top命令VIRT,RES,SHR,DATA的含义 字体: 大 小Posted by 佚名 | tags: top  VIRT  RES  SHR VIRT:virtual memory ...

  6. linux top 命令---VIRT,RES,SHR,虚拟内存和物理内存(

    VIRT,RES,SHR,虚拟内存和物理内存(转) VIRT: 1.进程"需要的"虚拟内存大小,包括进程使用的库.代码.数据,以及malloc.new分配的堆空间和分配的栈空间等: ...

  7. linux top命令VIRT,RES,SHR,DATA的含义

    VIRT:virtual memory usage 虚拟内存1.进程“需要的”虚拟内存大小,包括进程使用的库.代码.数据等2.假如进程申请100m的内存,但实际只使用了10m,那么它会增长100m,而 ...

  8. top 命令中的VIRT,RES,SHR ,MEM区别

    VIRT 表示进程的虚拟(地址)空间大小,其包含进程实际使用的大小(申请的堆栈), 使用mmap映射的大小,包括外设RAM, 还有映射到本进程的文件(例如动态库),还有进程间的共享内存.所以VIRT ...

  9. linux top命令看到的实存(RES)与虚存(VIRT)分析

    近期在公司中解决程序使用的内存高问题,将一部分之前无法回收的内存进行了回收,实现降内存效果(降实存). 在统计效果时, QA问是统计RES(实存)还是VIRT(虚存). 在网上学习看了一些博客,这里自 ...

随机推荐

  1. Servlet3.0提供的异步处理

    用属性asyncSupported=true开启Servlet对异步的支持. 在请求时,在request.startAsync()抛java.lang.IllegalStateException: N ...

  2. java线程总结(1/5)

    前言 闲来无事正值面试,看面试中有线程之问题,特此总结一番. 正文 一.线程和进程的区别:1.每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销.2.线程可以看成时轻量级的进程 ...

  3. 在k8s中的基本概念

    在k8s中的基本概念 一.Pod1. podk8s下最重要也最基本的概念,由一个根容器Pause和许多用户业务容器组成,是容器的载体. 2. pod的yaml定义格式及字段 apiVersion: v ...

  4. 算法笔记_098:蓝桥杯练习 算法提高 盾神与条状项链(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 问题描述 有一天,盾神捡到了好多好多五颜六色的珠子!他心想这些珠子这么漂亮,可以做成一条项链然后送给他心仪的女生~于是他用其中一些珠子做成了长度为n ...

  5. 【Windows】免费图片提取文字的方法

    今天意外的看到一个可以提取图片中文字的网站,自己试了下,提取效果还不错 网址为: https://zhcn.109876543210.com/ 现在有图片如下 我想从中提取的文字 1.打开网址,上传图 ...

  6. Hibernate 主配置文件详解

    摘要: 版权声明:本文为博主原创文章,如需转载请标注转载地址. 博客地址:http://www.cnblogs.com/caoyc/p/5595870.html 一.主配置文件命名规则 1.默认名称: ...

  7. Mybatis <Sql>标签

    重复的SQL预计永远不可避免,<sql>标签就是用来解决这个问题的 <sql id="sql1">id,name,age,gender</sql> ...

  8. jpush推送

    1.下载这个压缩包,vendo文件夹,复制里面的vendo到该文件夹下. 解压 2.修改AppKey和MasterSecret就ok 了

  9. Tcp/Ip--正常情况下的三次握手,四次挥手

    三次握手 四次挥手

  10. Asp.net2.0里的SessionPageStatePersister

    备注: ASP.NET 页可在处理和提供任何网页所必需的原本无状态 HTTP 请求与响应之间存储 Page 状态信息.此状态称为“视图状态”. ASP.NET 的默认持久性机制是使用 HiddenFi ...