[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 COMMAND
root 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 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
可以看出,雖然虛擬地址空間是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,最後用這個方法給系統中所有進程都“結下帳”:
12下一頁