对于linux free 命令:
free输出的第一行是从一个系统的角度看系统内存的使用情况
buffer是用于存放要输出到disk(块设备)的数据的
cache是存放从disk上读出的数据
这二者是为了提高IO性能的,并由OS管理。
free输出的第二行是从一个应用程序的角度看系统内存的使用情况
对于-buffers/cache,表示一个应用程序认为系统被用掉多少内存;
对于+buffers/cache,表示一个应用程序认为系统还有多少内存;
所以对于系统来说要看第一行的free,应用程序要看第二行的free
对于linux 单个进程来说:
- 进程所申请的内存不一定真正会被用到
- 真正用到了的内存也不一定是只有该进程自己在用 (比如动态共享库)
VSZ:进程内存空间的大小 如果进程映射了100M的内存, 进程的地址空间将报告为100M内存. 事实上, 这个大小不是一个程序实际使用的内存数
RSS:驻留物理内存中的内存大小(VSZ 和RSS 可以由ps aux 得到)"Resident Set Size", 实际驻留"在内存中"的内存数. 不包括已经交换出去的代码. 举一个例子: 如果你有一个程序使用了100K内存, 操作系统交换出40K内存, 那么RSS为60K. RSS还包括了与其它进程共享的内存区域. 这些区域通常用于libc库等.
SHARE: RSS中与其它进程共享的内存部分大小. SHARE 包含在RSS
VMSIZE: 一个进程占用的总的地址空间大小. 它包括了没有映到内存中的页面.
VMSIZE = VSZ + 没有映射到内存的页面
VSZ =RSS + 映射了但是没有使用的内存页面(交换出去了)
RSS = SHARE + Private RSS
Private RSS: 映射到内存中的页面, 这些页面仅由进程单独使用. 这也是我们最关心地方: 进程实际占用的内存数.主要通过读/proc/$pid/smaps获得(要想获得准确的,适用EXMAP工具)
ps命令计算的进程内存使用它是假设系统上只存在这唯一运行的进程时,此进程所占用的内存,所以不准:
RSS里面其实包括了共享库的内存大小,它计算的是所有共享库被它使用。
top命令的输出:
VIRT 进程使用的虚拟内存总量,单位kb。VIRT=SWAP+RES
SWAP 进程使用的虚拟内存中,被换出的大小,单位kb。RES 进程使用的、未被换出的物理内存大小,单位kb。RES=CODE+DATACODE 可执行代码占用的物理内存大小,单位kbDATA 可执行代码以外的部分(数据段+栈)占用的物理内存大小,单位kbSHR 共享内存大小,单位kbtop 内存利用率是由 RES/总的物理内存得到的
RES = RSS
VIRT = VSZ
这两个命令其实是一套体系的
下面的是一个什么体系?
Virtual memory : 52396 KBEffective VM : 52120 KBMapped : 352 KBEffective mapped: 76.6 KBSole use : 72 KB
Per file memory useld-2.3.4.so : VM 94208 B, M 90112 B, S 8192 Bprog : VM 8192 B, M 8192 B, S 8192 Blibc-2.3.4.so : VM 1180 KB, M 221184 B, S 16384 B
有效的实际使用内存 = 该进程独占的内存 + 共享的内存A /共享A的进程数目 + 共享的内存B /共享B的进程数目 + ...
---------------------------------------------------------------我是邪恶的分割线-----------------------------------------------------------------
解释一下Linux上free命令的输出。
下面是free的运行结果,一共有4行。为了方便说明,我们加上了列号。这样可以把free的输出看成一个二维数组FO(Free Output)。例如:
- FO[2][1] = 999212
- FO[3][2] = 305404 1 2 3 4 5 61 total used free shared buffers cached 2 Mem : 999212 967476 31736 0 50668 223000 3 -/+ buffers / cache : 693808 305404 4 Swap : 2048276 154524 1893752
free的输出一共有四行,第四行为交换区的信息,分别是交换的总量(total),使用量(used)和有多少空闲的交换区(free),这个比较清楚,不说太多。
free输出地第二行和第三行是比较让人迷惑的。这两行都是说明内存使用情况的。第一列是总量(total),第二列是使用量(used),第三列是可用量(free)。第一行的输出时从操作系统(OS)来看的。也就是说,从OS的角度来看,计算机上一共有:
- 999212KB(缺省时free的单位为KB)物理内存,即FO[2][1];
- 在这些物理内存中有967476KB(即FO[2][2])被使用了;
- 还用31736KB(即FO[2][3])是可用的;
这里得到第一个等式:
- FO[2][1] = FO[2][2] + FO[2][3]
FO[2][4]表示被几个进程共享的内存的,现在已经deprecated,其值总是0(当然在一些系统上也可能不是0,主要取决于free命令是怎么实现的)。
FO[2][5]表示被OS buffer住的内存。FO[2][6]表示被OS cache的内存。在有些时候buffer和cache这两个词经常混用。不过在一些比较低层的软件里是要区分这两个词的,看老外的洋文:
- A buffer is something that has yet to be "written" to disk.
- A cache is something that has been "read" from the disk and stored for later use.
也就是说buffer是用于存放要输出到disk(块设备)的数据的,而cache是存放从disk上读出的数据。这二者是为了提高IO性能的,并由OS管理。
Linux和其他成熟的操作系统(例如windows),为了提高IO read的性能,总是要多cache一些数据,这也就是为什么FO[2][6](cached memory)比较大,而FO[2][3]比较小的原因。我们可以做一个简单的测试:
- 释放掉被系统cache占用的数据; echo 3 >/ proc / sys / vm / drop_caches
- 读一个大文件,并记录时间;
- 关闭该文件;
- 重读这个大文件,并记录时间;
第二次读应该比第一次快很多。原来我做过一个BerkeleyDB的读操作,大概要读5G的文件,几千万条记录。在我的环境上,第二次读比第一次大概可以快9倍左右。
free输出的第二行是从一个应用程序的角度看系统内存的使用情况。
- 对于FO[3][2],即-buffers/cache,表示一个应用程序认为系统被用掉多少内存;
- 对于FO[3][3],即+buffers/cache,表示一个应用程序认为系统还有多少内存;
因为被系统cache和buffer占用的内存可以被快速回收,所以通常FO[3][3]比FO[2][3]会大很多。
这里还用两个等式:
- FO[3][2] = FO[2][2] - FO[2][5] - FO[2][6]
- FO[3][3] = FO[2][3] + FO[2][5] + FO[2][6]
这二者都不难理解。
free命令由procps.*.rpm提供(在Redhat系列的OS上)。free命令的所有输出值都是从/proc/meminfo中读出的。
在系统上可能有meminfo(2)这个函数,它就是为了解析/proc/meminfo的。procps这个包自己实现了meminfo()这个函数。可以下载一个procps的tar包看看具体实现,现在最新版式3.2.8。
转载自:http://pczou.bokee.com/5944730.htmlhttp://hi.baidu.com/shlongli/blog/item/5a244009ae1465cc3bc76322.html
进程的内存使用解析
进程XXX占用了多少内存?这是个经常被问到,也经常被答错的问题。Linux进程的内存分配是个比较复杂的话题,而Linux上的工具往往把这个问题过分简单化,因此引出不少误解和困惑。首先把ps, top这类工具扔掉,然后看这么一个简单程序:
[root@pczou pczou]# cat ./prog.c#i nclude <stdio.h>#i nclude <stdio.h>#i nclude <sys/types.h>#i nclude <unistd.h>#define ONEM (1024*1024)int func(){ char s[16*ONEM]; char* p; p = malloc(32*ONEM); pause(); return 0;}int main(){ printf("pid: %d\n", getpid()); func(); return 0;}
其中func()这个函数分配了32MB的内存,以及16MB的堆栈。运行一下这个prog程序,prog会停在pause()的位置,看看ps怎么说:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMANDroot 4238 0.0 0.0 52396 352 pts/0 S 21:29 0:00 ./prog
VSZ指的是进程内存空间的大小,这里是52396KB;RSS指的是驻留物理内存中的内存大小,这里是352KB。一般系统管理员知道VSZ并不代表进程真正用到的内存,因为有些空间会仅在页表中挂个名,也就是说只是虚拟存在着,只有真正用到的时候内核才会把虚拟页面和真正的物理页面映射起来。比如,prog.c中用malloc()分配的32MB内存,由于程序中并没有用到这些内存,没有物理内存被分配,也就不应算到进程的帐上。进程的内存使用情况比较复杂,这是因为:
- 进程所申请的内存不一定真正会被用到
- 真正用到了的内存也不一定是只有该进程自己在用 (比如动态共享库)
所以酒足饭饱结帐的时候,饭馆打出的帐单中往往漏洞百出,不是计入了没上的菜,就是一个菜算了两份钱。而ps给出的就是这样的“糊涂”帐单,不足为凭。算清楚帐的唯一办法是把每个菜都仔细过一遍,看看有没有上,有没有重复。下面的帐单要清楚多了:
Virtual memory : 52396 KBEffective VM : 52120 KBMapped : 352 KBEffective mapped: 76.6 KBSole use : 72 KBPer file memory useld-2.3.4.so : VM 94208 B, M 90112 B, S 8192 Bprog : VM 8192 B, M 8192 B, S 8192 Blibc-2.3.4.so : VM 1180 KB, M 221184 B, S 16384 B
可以看出,虽然虚拟地址空间是52396KB,实际映射(a.k.a. 分配)的空间是352KB,这和ps给出的结果一致。再看"Effective Mapped"这个值,仅为76.6 KB。这个值的计算方法是:
有效的实际使用内存 = 该进程独占的内存 + 共享的内存A /共享A的进程数目 + 共享的内存B /共享B的进程数目 + ...
比如对于一个kde应用程序kontact,它用的Qt库的虚拟地址空间为7M,而实际映射的空间有4.5M,也就是说真正给 Qt分配物理内存大小为4.5M。假设有10个KDE应用正在运行,那么记到kontact帐上的就不应该是4.5M,而是A-A之后的0.45M。这么算帐虽然并不十分准确,但"Effective Mapped"已经足以说明进程所占用内存的实际大小了。OK,最后用这个方法给系统中所有进程都“结下帐”:

从上面的统计结果可以看出:
- 虽然firefox的占用虚拟空间是最大的,但其实际占用的内存却比X Server要少。
- firefox 的实际占用的内存和其RSS (a.k.a. mapped)差别不大,占RSS的99%;而kontact的实际占用内存却仅占RSS的63%,有27%的内存是共享的。由此可以粗略看出我用的窗口管理器是KDE而非Gnome,why? 因为Qt之类的共享库被很多KDE进程分担了。
- sole值可以理解为"private mapped",也就是这个进程退出后可能被释放的内存 (对于非匿名的映射页面可能还会存留一段时间)。
参考资料:
- http://blog.zhaoke.com/31.html
- http://www.berthels.co.uk/exmap/
- http://projects.o-hand.com/#misc
- smaps
原文见:
先介绍几个基本概念: SIZE: 进程使用的地址空间, 如果进程映射了100M的内存, 进程的地址空间将报告为100M内存. 事实上, 这个大小不是一个程序实际使用的内存数. RSS: "Resident Set Size", 实际驻留"在内存中"的内存数. 不包括已经交换出去的代码. 举一个例子: 如果你有一个程序使用了100K内存, 操作系统交换出40K内存, 那么RSS为60K. RSS还包括了与其它进程共享的内存区域. 这些区域通常用于libc库等. SHARE: RSS中与其它进程共享的内存部分大小. VMSIZE: 一个进程占用的总的地址空间大小. 它包括了没有映射到内存中的页面. Private RSS: 映射到内存中的页面, 这些页面仅由进程单独使用. 这也是我们最关心地方: 进程实际占用的内存数. 如何来查看Private RSS呢? /proc接口中每一个进程目录下的smaps提供了private rss信息. smaps是在2.6.16内核版本引进来的. 私有驻留内存数(Private RSS):查看/proc/$pid/smaps 下面我以本站使用的Fedora Core 5为例, 查看进程号1293(vmware-guestd, 本站使用的是一台基于vmware的客户虚拟机, )使用的Private RSS数. CODE: # cat /proc/1293/smaps 00111000-00112000 rwxp 00111000 00:00 0 Size: 4 kBRss: 4 kBShared_Clean: 0 kBShared_Dirty: 0 kBPrivate_Clean: 0 kBPrivate_Dirty: 4 kB0050e000-0050f000 rwxp 0050e000 00:00 0 Size: 4 kBRss: 0 kBShared_Clean: 0 kBShared_Dirty: 0 kBPrivate_Clean: 0 kBPrivate_Dirty: 0 kB0051a000-0051b000 r-xp 0051a000 00:00 0 [vdso]Size: 4 kBRss: 4 kBShared_Clean: 4 kBShared_Dirty: 0 kBPrivate_Clean: 0 kBPrivate_Dirty: 0 kB0051b000-00534000 r-xp 00000000 fd:00 194898 /lib/ld-2.4.soSize: 100 kBRss: 0 kBShared_Clean: 0 kBShared_Dirty: 0 kBPrivate_Clean: 0 kBPrivate_Dirty: 0 kB00534000-00535000 r-xp 00018000 fd:00 194898 /lib/ld-2.4.soSize: 4 kBRss: 0 kBShared_Clean: 0 kBShared_Dirty: 0 kBPrivate_Clean: 0 kBPrivate_Dirty: 0 kB00535000-00536000 rwxp 00019000 fd:00 194898 /lib/ld-2.4.soSize: 4 kBRss: 0 kBShared_Clean: 0 kBShared_Dirty: 0 kBPrivate_Clean: 0 kBPrivate_Dirty: 0 kB00538000-00665000 r-xp 00000000 fd:00 194905 /lib/libc-2.4.soSize: 1204 kBRss: 212 kBShared_Clean: 204 kBShared_Dirty: 0 kBPrivate_Clean: 8 kBPrivate_Dirty: 0 kB00665000-00667000 r-xp 0012d000 fd:00 194905 /lib/libc-2.4.soSize: 8 kBRss: 8 kBShared_Clean: 4 kBShared_Dirty: 0 kBPrivate_Clean: 0 kBPrivate_Dirty: 4 kB00667000-00668000 rwxp 0012f000 fd:00 194905 /lib/libc-2.4.soSize: 4 kBRss: 4 kBShared_Clean: 0 kBShared_Dirty: 0 kBPrivate_Clean: 0 kBPrivate_Dirty: 4 kB00668000-0066b000 rwxp 00668000 00:00 0 Size: 12 kBRss: 8 kBShared_Clean: 0 kBShared_Dirty: 0 kBPrivate_Clean: 0 kBPrivate_Dirty: 8 kB08047000-08062000 r-xp 00000000 fd:00 292327 /usr/sbin/vmware-guestdSize: 108 kBRss: 64 kBShared_Clean: 0 kBShared_Dirty: 0 kBPrivate_Clean: 64 kBPrivate_Dirty: 0 kB08062000-08063000 rwxp 0001a000 fd:00 292327 /usr/sbin/vmware-guestdSize: 4 kBRss: 4 kBShared_Clean: 0 kBShared_Dirty: 0 kBPrivate_Clean: 0 kBPrivate_Dirty: 4 kB08063000-08068000 rwxp 08063000 00:00 0 Size: 20 kBRss: 12 kBShared_Clean: 0 kBShared_Dirty: 0 kBPrivate_Clean: 0 kBPrivate_Dirty: 12 kB08385000-08886000 rwxp 08385000 00:00 0 [heap]Size: 5124 kBRss: 5080 kBShared_Clean: 0 kBShared_Dirty: 0 kBPrivate_Clean: 0 kBPrivate_Dirty: 5080 kBbfeb2000-bfec7000 rwxp bfeb2000 00:00 0 [stack]Size: 84 kBRss: 12 kBShared_Clean: 0 kBShared_Dirty: 0 kBPrivate_Clean: 0 kBPrivate_Dirty: 12 kB 上面我们看到从smaps看不太方便, 推荐使用Ben Maurer写的: (本地) 下面是由seme.pl脚本解析的smaps数据: 首先安装Linux::Smaps模块:perl -MCPAN -e 'install Linux::Smaps' 然后用seme.pl解析1293进程的Smaps数据: CODE: # ./smem.pl 1293VMSIZE: 7200 kbRSS: 1052 kb total192 kb shared100 kb private clean760 kb private dirtyPRIVATE MAPPINGSvmsize rss clean rss dirty file5636 kb 8 kb 724 kb [heap]84 kb 0 kb 12 kb [stack]4 kb 0 kb 4 kb8 kb 0 kb 4 kb /lib/libc-2.4.so4 kb 0 kb 4 kb /lib/libc-2.4.so12 kb 4 kb 4 kb4 kb 0 kb 4 kb /usr/sbin/vmware-guestd20 kb 8 kb 4 kb1204 kb 16 kb 0 kb /lib/libc-2.4.so108 kb 64 kb 0 kb /usr/sbin/vmware-guestd SHARED MAPPINGSvmsize rss clean rss dirty file1204 kb 188 kb 0 kb /lib/libc-2.4.so4 kb 4 kb 0 kb [vdso] 从上面看到rss大小被分成了两个部分: private(私有)和shared(共享).private rss就是我们最关心的进程实际占用的内存数. 参考:1. 2. smaps and maps, also proc man pages.3. |
关键字: linux