Top命令内存占用剖析
原文: http://yalung929.blog.163.com/blog/static/203898225201212981731971/
引 言: 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命令内存占用剖析的更多相关文章
- Android使用procrank和dumpsys meminfo 、top分析内存占用情况
如果你想查看所有进程的内存使用情况,可以使用命令procrank.dumpsys meminfo查看,当然也只可以过滤出某个进程如:dumpsys meminfo | grep -i phone 先来 ...
- Linux的top命令cpu占用少,但是显示很高
最近发现服务器一个奇怪的问题,40核的双路服务器,装的centos7.4系统,开机过几个小时后会图形界面特别卡顿,top里发现CPU使用率50%左右,但是进程里没有大量占用的进程.怎么上传不了图片.. ...
- Ubuntu 使用top/free查看内存占用大的原因
Ubuntu 使用top/free查看内存占用大的原因 linux/ubuntu下free/top查看内存占用大的原因 使用free/top查看内存占用的时候,吓了一大跳,机器4GB的内存,显 ...
- 【linux】查看系统内存占用
1.查看内存情况 free -h 解释下基本概念 Mem 内存的使用信息Swap 交换空间的使用信息total 系统总的可用物理内存大小used 已被使用的物理内存大小free 还有多少物理内存可用s ...
- Java中的CPU占用高和内存占用高的问题排查
下面通过模拟实例分析排查Java应用程序CPU和内存占用过高的过程.如果是Java面试,这2个问题在面试过程中出现的概率很高,所以我打算在这里好好总结一下. 1.Java CPU过高的问题排查 举个例 ...
- Linux TOP命令按内存占用排序和按CPU占用排序
先输入top 然后 按P – 以 CPU 占用率大小的顺序排列进程列表 按M – 以内存占用率大小的顺序排列进程列表 top命令是Linux下常用的性能分析工具,比如cpu.内存的使用,能够实时显示系 ...
- 转 linux进程内存到底怎么看 剖析top命令显示的VIRT RES SHR值
引 言: top命令作为Linux下最常用的性能分析工具之一,可以监控.收集进程的CPU.IO.内存使用情况.比如我们可以通过top命令获得一个进程使用了多少虚拟内存(VIRT).物理内存(RES). ...
- linux进程内存到底怎么看 剖析top命令显示的VIRT RES SHR值
引 言: top命令作为Linux下最常用的性能分析工具之一,可以监控.收集进程的CPU.IO.内存使用情况.比如我们可以通过top命令获得一个进程使用了多少虚拟内存(VIRT).物理内存(RES). ...
- linux top命令查看内存及多核CPU的使用讲述
查看多核CPU命令 mpstat -P ALL 和 sar -P ALL 说明:sar -P ALL > aaa.txt 重定向输出内容到文件 aaa.txt top命令 经常用来监控l ...
随机推荐
- Unity 5.4大赞:HTC Vive经典The lab渲染器开源
HTC Vive提供了一个不错的免费VR demo,最近1周仔细体验了一番. 仔细看了其安装文件,竟然是Unity 5.4beta版本(通过查log,知道Valve公司用的是最新的5.4.0b11版本 ...
- 移动端高清、多屏适配方案 [来源:http://div.io/topic/1092]
Lovesueee 发布于 8 月前 移动端高清.多屏适配方案 背景 开发移动端H5页面 面对不同分辨率的手机 面对不同屏幕尺寸的手机 视觉稿 在前端开发之前,视觉MM会给我们一个psd文件,称之为视 ...
- less使用001
官网: http://lesscss.org/ . 中文文档直接百度搜索less,能找到N多网站提供的支持. less-gui,使用国产的koala, 其中文帮助文档地址. 拖拽一个目录到考拉就新建了 ...
- StringBuilder和StringBuffer
StringBuilder java.lang 类 StringBuilder java.lang.Object java.lang.StringBuilder 所有已实现的接口: Serializa ...
- linux网络编程九:splice函数,高效的零拷贝
from:http://blog.csdn.net/jasonliuvip/article/details/22600569 linux网络编程九:splice函数,高效的零拷贝 最近在看<Li ...
- 【C#高级编程(学习与理解)】1.1 C#与.NET的关系
1.C#语言不能孤立使用,而必须和.NET Framework一起考虑.C#编译器专门用于.NET,这表示用C#编写的所有代码总是在.NET Framework中运行. 2.C#就其本身而言只是一种语 ...
- javascript截取字符串(支持中英文混合)
javascript截取字符串(支持中英文混合) <script type="text/javascript"> var sub=function(str,n){ va ...
- php总结:1.php介绍
1.什么是php PHP,即“Hypertext Preprocessor”,是一种被广泛应用的开源通用脚本语言,尤其适用于 Web 开发并可嵌入 HTML 中去.它的语法利用了 C.Java 和 P ...
- Programming Collective Intelligence
最近正在拜读 O'reilly出版的Programming Collective Intelligence,准备研究研究搜索引擎了,童鞋们,到时候会考虑公布源码哦!
- POJ 1001 解题报告 高精度大整数乘法模版
题目是POJ1001 Exponentiation 虽然是小数的幂 最终还是转化为大整数的乘法 这道题要考虑的边界情况比较多 做这道题的时候,我分析了 网上的两个解题报告,发现都有错误,说明OJ对于 ...