- 在linux下,查看
一个运行中的程序, 占用了多少内存
, 一般的命令有
(1). ps aux:
参数解析:
- VSZ(或VSS)列 表示,程序占用了多少
虚拟内存
- RSS列 表示, 程序占用了多少
物理内存
虚拟内存
可以不用考虑,它并不占用实际物理内存
实例:
#ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 19360 1528 ? Ss Jul18 0:00 /sbin/init
root 2 0.0 0.0 0 0 ? S Jul18 0:01 [kthreadd]
root 3 0.0 0.0 0 0 ? S Jul18 0:00 [migration/0]
root 4 0.0 0.0 0 0 ? S Jul18 74:00 [ksoftirqd/0]
root 5 0.0 0.0 0 0 ? S Jul18 0:00 [migration/0]
root 6 0.0 0.0 0 0 ? S Jul18 0:09 [watchdog/0]
root 7 0.0 0.0 0 0 ? S Jul18 0:15 [migration/1]
root 8 0.0 0.0 0 0 ? S Jul18 0:00 [migration/1]
root 9 0.0 0.0 0 0 ? S Jul18 42:05 [ksoftirqd/1]
root 10 0.0 0.0 0 0 ? S Jul18 0:07 [watchdog/1]
root 11 0.0 0.0 0 0 ? S Jul18 0:02 [migration/2]
root 12 0.0 0.0 0 0 ? S Jul18 0:00 [migration/2]
root 13 0.0 0.0 0 0 ? S Jul18 18:26 [ksoftirqd/2]
root 14 0.0 0.0 0 0 ? S Jul18 0:06 [watchdog/2]
(2). 使用 top 命令
- 其中 VIRT(或VSS)列 表示,程序占用了多少虚拟内存。 同 ps aux 中的 VSZ列
- RES列 表示, 程序占用了多少物理内存。同 ps aux 中的RSS列
实例:
#top
top - 19:41:09 up 97 days, 10:44, 1 user, load average: 0.04, 0.01, 0.00
Tasks: 424 total, 1 running, 423 sleeping, 0 stopped, 0 zombie
Cpu(s): 0.0%us, 0.0%sy, 0.0%ni, 99.9%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 16333244k total, 5963824k used, 10369420k free, 536076k buffers
Swap: 10485752k total, 0k used, 10485752k free, 1859516k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
2762 jbossuse 20 0 17.4g 3.0g 35m S 0.3 19.5 1:48.00 java
12789 root 20 0 15304 1552 972 R 0.3 0.0 0:00.03 top
1 root 20 0 19360 1528 1216 S 0.0 0.0 0:00.99 init
2 root 20 0 0 0 0 S 0.0 0.0 0:01.37 kthreadd
2.在linux下, 查看当前系统占用了多少内存, 一般的命令是 free(默认单位kb, 其他单位: -g | -m)
其中, free就是系统还有多少内存可以使用。
但由于 linux 系统对内存使用有一个原则, 就是, 内存是宝贵的, 能使用多少就使用多少。 所以, linux会把已经调用过的包缓存起来,放在内存里。
这样,实际上,可以使用的内存,就可以理解为, free+buffers+cached
3.当你了解完这些命令以后, 再去使用ps aux 命令去查看的时候, 会发现一个奇怪的现象。
所有的 RSS 列的数据,加起来, 比物理内存的数要大很多。
比如, 物理内存为2G, 而RSS列的数据加起来,可能有5个G之多, 这是怎么回事了?
这是因为RSS列的值骗了我们。
linux的内存机制是这样的:
在运行一个程序时, linux会调用该程序依赖的链接库, 如lib.xx.so。 首先看该链接库是否被映射进内存中,如果没有被映射,则将代码段与数据段映射到内存中,否则只是将其加入进程的地址空间。
这样,当N个程序,依赖到lib.xx.so的时候, 实际上,内存中只有一个lib.xx.so ,而不是N个。
而RSS在显示一个程序占用的实际物理内存时, 将lib.xx.so也算了进来。
比如, X程序, 本身占用内存为5M, lib.xx.so 占用内存2M,lib.xx.so被N个程序共享依赖。 则RSS显示为,X程序运行,占用内存为7M。 实际上, X程序占用了5M空间。 多余的2m被讨入到RSS中了。
当你在用ps aux显示内存占用情况时, N个共享依赖lib.xx.so的N个程序,都把这2m空间,算在自己的RSS中了, 这样RSS的sum值,就比实际物理内存多了。
当然, linux的内存使用机制很复杂, 不是一句两句能说清楚的。这里只是简单的说明了一下, ps aux中的RSS值, 并不能真实反映物理内存的使用情况。
- 如果查看更详细的内存使用情况, 可用以下几种方法, 或者几种方法结合使用:
这几种方法,都需要root账户的权限
(1). pmap -d $pid
$pid 是正在运行的程序的pid
502 2762 2682 0 11:54 ? 00:01:48 /opt/wildfly/java64/jdk1.7.0_25/bin/java -D[Standalone] -server -Xms4096m -Xmx8192m -XX:MaxPermSize=512m -Djava.net.preferIPv4Stack=true -Dfile.......
(2). cat /proc/$pid/smaps
smaps的数据比较详细,可简单的归纳一下,归纳的命令如下:
cat /proc/$pid/smaps | awk '/Size|Rss|Pss|Shared|Private|Referenced|Swap/{val_name=gensub(/([a-zA-Z_]*).*/,"\\1",1,$1); list[val_name]+=$2; }END{for(val in list)print val,list[val];}'
(3). cat /proc/$pid/maps
# cat /proc/6534/maps
60bc00000-67e000000 rw-p 00000000 00:00 0
67e000000-800000000 ---p 00000000 00:00 0
800000000-80043b000 rw-p 00000000 00:00 0
80043b000-840000000 ---p 00000000 00:00 0
5613282d1000-5613282d2000 r-xp 00000000 fd:01 2391926 /opt/software/jdk-11.0.7/bin/java
5613284d2000-5613284d3000 r--p 00001000 fd:01 2391926 /opt/software/jdk-11.0.7/bin/java
5613284d3000-5613284d4000 rw-p 00002000 fd:01 2391926 /opt/software/jdk-11.0.7/bin/java
561328a60000-561328a81000 rw-p 00000000 00:00 0 [heap]
7f87c4000000-7f87c4021000 rw-p 00000000 00:00 0
7f87c4021000-7f87c8000000 ---p 00000000 00:00 0
(4). cat /proc/$pid/statm
# cat /proc/2762/statm
4569543 795414 9116 1 0 4494492 0
输出解释
第一列 size:任务虚拟地址空间大小
第二列 Resident:正在使用的物理内存大小
第三列 Shared:共享页数
第四列 Trs:程序所拥有的可执行虚拟内存大小
第五列 Lrs:被映像倒任务的虚拟内存空间的库的大小
第六列 Drs:程序数据段和用户态的栈的大小
第七列 dt:脏页数量