分类: LINUX
2010-05-03 23:27:45
进程XXX占用了多少内存?这是个经常被问到,也经常被答错的问题。Linux进程的内存分配是个比较复杂的话题,
而Linux上的工具往往把这个问题过分简单化,因此引出不少误解和困惑。首先把ps, top这类工具扔掉,然后看这么一个简单程序:
[root@pczou pczou]# cat ./prog.c
#i nclude
#i nclude
#i nclude
#i nclude
#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;
}
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMANDVSZ指的是进程内存空间的大小,这里是52396KB;
root 4238 0.0 0.0 52396 352 pts/0 S 21:29 0:00 ./prog
Virtual memory : 52396 KB
Effective VM : 52120 KB
Mapped : 352 KB
Effective mapped: 76.6 KB
Sole use : 72 KB
Per file memory use
ld-2.3.4.so : VM 94208 B, M 90112 B, S 8192 B
prog : VM 8192 B, M 8192 B, S 8192 B
libc-2.3.4.so : VM 1180 KB, M 221184 B, S 16384 B
有效的实际使用内存 = 该进程独占的内存 + 共享的内存A /共享A的进程数目 + 共享的内存B /共享B的进程数目 + ...比如对于一个kde应用程序kontact,它用的Qt库的虚拟地址空间为 7M,而实际映射的空间有4.5M,也就是说真正给 Qt分配物理内存大小为4.5M。假设有10个KDE应用正在运行,那么记到kontact帐上的就不应该是4.5M,而是A-A之后的0.45M。这么 算帐虽然并不十分准确,但"Effective Mapped"已经足以说明进程所占用内存的实际大小了。
先介绍几个基本概念: 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): 下面我以本站使用的Fedora Core 5为例, 查看进程号1293(vmware-guestd, 本站使用的是一台基于vmware的客户虚拟机, )使用的Private RSS数. CODE:
# cat /proc/1293/smaps
00111000-00112000 rwxp 00111000 00:00 0 Size: 4 kB Rss: 4 kB Shared_Clean: 0 kB Shared_Dirty: 0 kB Private_Clean: 0 kB Private_Dirty: 4 kB 0050e000-0050f000 rwxp 0050e000 00:00 0 Size: 4 kB Rss: 0 kB Shared_Clean: 0 kB Shared_Dirty: 0 kB Private_Clean: 0 kB Private_Dirty: 0 kB 0051a000-0051b000 r-xp 0051a000 00:00 0 [vdso] Size: 4 kB Rss: 4 kB Shared_Clean: 4 kB Shared_Dirty: 0 kB Private_Clean: 0 kB Private_Dirty: 0 kB 0051b000-00534000 r-xp 00000000 fd:00 194898 /lib/ld-2.4.so Size: 100 kB Rss: 0 kB Shared_Clean: 0 kB Shared_Dirty: 0 kB Private_Clean: 0 kB Private_Dirty: 0 kB 00534000-00535000 r-xp 00018000 fd:00 194898 /lib/ld-2.4.so Size: 4 kB Rss: 0 kB Shared_Clean: 0 kB Shared_Dirty: 0 kB Private_Clean: 0 kB Private_Dirty: 0 kB 00535000-00536000 rwxp 00019000 fd:00 194898 /lib/ld-2.4.so Size: 4 kB Rss: 0 kB Shared_Clean: 0 kB Shared_Dirty: 0 kB Private_Clean: 0 kB Private_Dirty: 0 kB 00538000-00665000 r-xp 00000000 fd:00 194905 /lib/libc-2.4.so Size: 1204 kB Rss: 212 kB Shared_Clean: 204 kB Shared_Dirty: 0 kB Private_Clean: 8 kB Private_Dirty: 0 kB 00665000-00667000 r-xp 0012d000 fd:00 194905 /lib/libc-2.4.so Size: 8 kB Rss: 8 kB Shared_Clean: 4 kB Shared_Dirty: 0 kB Private_Clean: 0 kB Private_Dirty: 4 kB 00667000-00668000 rwxp 0012f000 fd:00 194905 /lib/libc-2.4.so Size: 4 kB Rss: 4 kB Shared_Clean: 0 kB Shared_Dirty: 0 kB Private_Clean: 0 kB Private_Dirty: 4 kB 00668000-0066b000 rwxp 00668000 00:00 0 Size: 12 kB Rss: 8 kB Shared_Clean: 0 kB Shared_Dirty: 0 kB Private_Clean: 0 kB Private_Dirty: 8 kB 08047000-08062000 r-xp 00000000 fd:00 292327 /usr/sbin/vmware-guestd Size: 108 kB Rss: 64 kB Shared_Clean: 0 kB Shared_Dirty: 0 kB Private_Clean: 64 kB Private_Dirty: 0 kB 08062000-08063000 rwxp 0001a000 fd:00 292327 /usr/sbin/vmware-guestd Size: 4 kB Rss: 4 kB Shared_Clean: 0 kB Shared_Dirty: 0 kB Private_Clean: 0 kB Private_Dirty: 4 kB 08063000-08068000 rwxp 08063000 00:00 0 Size: 20 kB Rss: 12 kB Shared_Clean: 0 kB Shared_Dirty: 0 kB Private_Clean: 0 kB Private_Dirty: 12 kB 08385000-08886000 rwxp 08385000 00:00 0 [heap] Size: 5124 kB Rss: 5080 kB Shared_Clean: 0 kB Shared_Dirty: 0 kB Private_Clean: 0 kB Private_Dirty: 5080 kB bfeb2000-bfec7000 rwxp bfeb2000 00:00 0 [stack] Size: 84 kB Rss: 12 kB Shared_Clean: 0 kB Shared_Dirty: 0 kB Private_Clean: 0 kB Private_Dirty: 12 kB 上面我们看到从smaps看不太方便, 推荐使用Ben Maurer写的: (本地下载) 下面是由seme.pl脚本解析的smaps数据: 首先安装Linux::Smaps模块: 然后用seme.pl解析1293进程的Smaps数据: CODE:
# ./smem.pl 1293
VMSIZE: 7200 kb RSS: 1052 kb total 192 kb shared 100 kb private clean 760 kb private dirty PRIVATE MAPPINGS vmsize rss clean rss dirty file 5636 kb 8 kb 724 kb [heap] 84 kb 0 kb 12 kb [stack] 4 kb 0 kb 4 kb 8 kb 0 kb 4 kb /lib/libc-2.4.so 4 kb 0 kb 4 kb /lib/libc-2.4.so 12 kb 4 kb 4 kb 4 kb 0 kb 4 kb /usr/sbin/vmware-guestd 20 kb 8 kb 4 kb 1204 kb 16 kb 0 kb /lib/libc-2.4.so 108 kb 64 kb 0 kb /usr/sbin/vmware-guestd SHARED MAPPINGS 从上面看到rss大小被分成了两个部分:
private(私有)和shared(共享). 参考: |