文章目录
前言
前面我们已经学习了 CPU 篇,这篇来看下内存篇。
内存信息
/proc/meminfo
这个文件记录着比较详细的内存配置信息,使用 cat /proc/meminfo 查看。
[root@master ~]# cat /proc/meminfo
MemTotal: 1863196 kB
系统总内存,由于 BIOS、内核等会占用一些内存,所以这里和配置声称的内存会有一些出入,比如我这里配置有 2G,但其实只有 1.51G 可用。
MemFree: 121916 kB
系统空闲内存。
MemAvailable: 551240 kB
应用程序可用内存。有人会比较奇怪和 MemFree 的区别,可以从两个层面来区分,MemFree 是系统层面的,而 MemAvailable 是应用程序层面的。系统中有些内存虽然被使用了但是有一部分是可以回收的,比如 Buffers、Cached 及 Slab 这些内存,这部分可以回收的内存加上 MemFree 才是 MemAvailable 的内存值,这是内核通过特定算法算出来的,是一个估算值。
Buffers: 204 kB
缓冲区内存
Cached: 539568 kB
缓存
SwapCached: 0 kB
Active: 955436 kB
Inactive: 367568 kB
Active(anon): 761336 kB
Inactive(anon): 36160 kB
Active(file): 194100 kB
Inactive(file): 331408 kB
Unevictable: 0 kB
Mlocked: 0 kB
SwapTotal: 2097148 kB
SwapFree: 2097148 kB
Dirty: 4 kB
Writeback: 0 kB
AnonPages: 783228 kB
Mapped: 134288 kB
Shmem: 14264 kB
Slab: 127384 kB
SReclaimable: 69812 kB
SUnreclaim: 57572 kB
KernelStack: 11040 kB
PageTables: 42224 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 3028744 kB
Committed_AS: 4617028 kB
VmallocTotal: 34359738367 kB
VmallocUsed: 185664 kB
VmallocChunk: 34359310332 kB
HardwareCorrupted: 0 kB
AnonHugePages: 122880 kB
CmaTotal: 0 kB
CmaFree: 0 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
DirectMap4k: 141184 kB
DirectMap2M: 1955840 kB
DirectMap1G: 0 kB
上面信息没有 MemUsed 的值,虽然可以用现有的值大致估算出来,但是我们想一步到位,就用下面的 free 命令。
free
这个命令估计用的人就多了(我一般都是用这个命令)。
这里存在一个计算公式:
MemTotal = used + free + buff/cache(单位 K)
几个字段和上面 /proc/meminfo 的字段是对应的。还有个 shared 字段,这个是多进程的共享内存空间,不常用。
我们注意到 free 很小,buff/cache 却很大,这是 Linux 的内存设计决定的,Linux 的想法是内存闲着反正也是闲着,不如拿出来做系统缓存和缓冲区,提高数据读写的速率。但是当系统内存不足时,buff/cache 会让出部分来,非常灵活的操作。
要看比较直观的值,可以加 -h 参数
dmidecode
同样可以使用这个命令,对于内存,可以使用 dmidecode -t memory 查看:
[root@master ~]# dmidecode -t memory |grep Size
Maximum Memory Module Size: 32768 MB
Maximum Total Memory Size: 491520 MB
Installed Size: 2048 MB (Single-bank Connection)
Enabled Size: 2048 MB (Single-bank Connection)
Installed Size: Not Installed
Maximum Memory Module Size: 32768 MB,Maximum Total Memory Size: 491520 MB怎么这么大,这是做什么用的?
vmstat
这个命令也是非常常用了。但对于内存,显示信息有限。它更多是用于进行系统全局分析和 CPU 分析。详细可以看 CPU 分析一文。
进程内存使用情况分析
最常用的两个命令 ps 和 top,虽然很简单的两个命令,但还是有不少学问的。
top 命令运行时默认是按照 CPU 利用率进行排序的,如果要按照内存排序,该怎么操作呢?两种方法,一种直接按 “M”(相应的按 “P” 是 CPU),另外一种是在键入 top 之后,按下 “F”,然后选择要排序的字段,再按下 “s” 确认即可。
可以看到,我按照 “%MEM” 排序的结果。这个结果对于查看系统占用内存较多的哪些进程是比较有用的。
然后这里我们会重点关注几个地方,上面横排区,和前面几个命令一样可以查看系统内存信息,中间标注的横条部分,和内存相关的有三个字段:VIRT、RES、SHR。
- VIRT:virtual memory usage,进程占用的虚拟内存大小。
- RES:resident memory usage,进程常驻内存大小,也就是实际内存占用情况,一般我们看进程占用了多少内存,就是看的这个值。
- SHR:shared memory,共享内存大小,不常用。
ps
ps 同样可以查看进程占用内存情况,一般常用来查看 Top n 进程占用内存情况,如:
ps aux --sort=rss | head -n,表示按 rss 排序,取 Top n。
[root@master ~]# ps aux --sort=vsz | head -10
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 2 0.0 0.0 0 0 ? S 09:59 0:00 [kthreadd]
root 3 0.0 0.0 0 0 ? S 09:59 0:00 [ksoftirqd/0]
root 5 0.0 0.0 0 0 ? S< 09:59 0:00 [kworker/0:0H]
root 7 0.0 0.0 0 0 ? S 09:59 0:00 [migration/0]
root 8 0.0 0.0 0 0 ? S 09:59 0:00 [rcu_bh]
root 9 0.0 0.0 0 0 ? R 09:59 0:03 [rcu_sched]
root 10 0.0 0.0 0 0 ? S< 09:59 0:00 [lru-add-drain]
root 11 0.0 0.0 0 0 ? S 09:59 0:00 [watchdog/0]
root 13 0.0 0.0 0 0 ? S 09:59 0:00 [kdevtmpfs]
这里也关注三个字段:
- %MEM:进程使用物理内存所占百分比。
- VSZ:进程使用虚拟内存大小。
- RSS:进程使用物理内存大小,我们会重点关注这个值。
pmap
这个命令用于查看进程的内存映像信息,能够查看进程在哪些地方用了多少内存。 常用 pmap -x pid 来查看。
[root@master ~]# pmap -x 7501
7501: /usr/sbin/sshd -D
Address Kbytes RSS Dirty Mode Mapping
0000563423750000 800 284 0 r-x-- sshd
0000563423a17000 16 16 16 r---- sshd
0000563423a1b000 4 4 4 rw--- sshd
0000563423a1c000 36 36 36 rw--- [ anon ]
0000563423fba000 132 60 60 rw--- [ anon ]
00007f600838e000 48 20 0 r-x-- libnss_files-2.17.so
00007f600839a000 2044 0 0 ----- libnss_files-2.17.so
00007f6008599000 4 4 4 r---- libnss_files-2.17.so
00007f600859a000 4 4 4 rw--- libnss_files-2.17.so
00007f600859b000 24 0 0 rw--- [ anon ]
00007f60085a1000 60 8 0 r-x-- libbz2.so.1.0.6
00007f60085b0000 2044 0 0 ----- libbz2.so.1.0.6
00007f60087af000 4 4 4 r---- libbz2.so.1.0.6
00007f60087b0000 4 4 4 rw--- libbz2.so.1.0.6
00007f60087b1000 92 16 0 r-x-- libelf-0.172.so
00007f60087c8000 2044 0 0 ----- libelf-0.172.so
00007f60089c7000 4 4 4 r---- libelf-0.172.so
00007f60089c8000 4 4 4 rw--- libelf-0.172.so
00007f60089c9000 16 8 0 r-x-- libattr.so.1.1.0
00007f60089cd000 2044 0 0 ----- libattr.so.1.1.0
00007f6008bcc000 4 4 4 r---- libattr.so.1.1.0
00007f6008bcd000 4 4 4 rw--- libattr.so.1.1.0
00007f6008bce000 12 8 0 r-x-- libkeyutils.so.1.5
00007f6008bd1000 2044 0 0 ----- libkeyutils.so.1.5
00007f6008dd0000 4 4 4 r---- libkeyutils.so.1.5
00007f6008dd1000 4 4 4 rw--- libkeyutils.so.1.5
00007f6008dd2000 52 16 0 r-x-- libkrb5support.so.0.1
00007f6008ddf000 2048 0 0 ----- libkrb5support.so.0.1
00007f6008fdf000 4 4 4 r---- libkrb5support.so.0.1
00007f6008fe0000 4 4 4 rw--- libkrb5support.so.0.1
00007f6008fe1000 8 4 0 r-x-- libfreebl3.so
00007f6008fe3000 2044 0 0 ----- libfreebl3.so
00007f60091e2000 4 4 4 r---- libfreebl3.so
00007f60091e3000 4 4 4 rw--- libfreebl3.so
00007f60091e4000 232 52 0 r-x-- libnspr4.so
00007f600921e000 2044 0 0 ----- libnspr4.so
00007f600941d000 4 4 4 r---- libnspr4.so
00007f600941e000 8 8 8 rw--- libnspr4.so
00007f6009420000 8 0 0 rw--- [ anon ]
00007f6009422000 16 8 0 r-x-- libplc4.so
00007f6009426000 2044 0 0 ----- libplc4.so
00007f6009625000 4 4 4 r---- libplc4.so
00007f6009626000 4 4 4 rw--- libplc4.so
00007f6009627000 12 4 0 r-x-- libplds4.so
00007f600962a000 2044 0 0 ----- libplds4.so
00007f6009829000 4 4 4 r---- libplds4.so
00007f600982a000 4 4 4 rw--- libplds4.so
00007f600982b000 160 52 0 r-x-- libnssutil3.so
00007f6009853000 2044 0 0 ----- libnssutil3.so
00007f6009a52000 28 28 28 r---- libnssutil3.so
00007f6009a59000 4 4 4 rw--- libnssutil3.so
00007f6009a5a000 1168 100 0 r-x-- libnss3.so
00007f6009b7e000 2048 0 0 ----- libnss3.so
00007f6009d7e000 20 20 20 r---- libnss3.so
00007f6009d83000 8 8 8 rw--- libnss3.so
00007f6009d85000 8 0 0 rw--- [ anon ]
00007f6009d87000 144 40 0 r-x-- libsmime3.so
00007f6009dab000 2044 0 0 ----- libsmime3.so
00007f6009faa000 12 12 12 r---- libsmime3.so
00007f6009fad000 4 4 4 rw--- libsmime3.so
00007f6009fae000 308 52 0 r-x-- libssl3.so
00007f6009ffb000 2044 0 0 ----- libssl3.so
00007f600a1fa000 16 16 16 r---- libssl3.so
00007f600a1fe000 4 4 4 rw--- libssl3.so
00007f600a1ff000 4 0 0 rw--- [ anon ]
00007f600a200000 412 104 0 r-x-- libssl.so.1.0.2k
00007f600a267000 2048 0 0 ----- libssl.so.1.0.2k
00007f600a467000 16 16 16 r---- libssl.so.1.0.2k
00007f600a46b000 28 28 28 rw--- libssl.so.1.0.2k
00007f600a472000 112 20 0 r-x-- libsasl2.so.3.0.0
00007f600a48e000 2044 0 0 ----- libsasl2.so.3.0.0
00007f600a68d000 4 4 4 r---- libsasl2.so.3.0.0
00007f600a68e000 4 4 4 rw--- libsasl2.so.3.0.0
00007f600a68f000 92 60 0 r-x-- libpthread-2.17.so
00007f600a6a6000 2044 0 0 ----- libpthread-2.17.so
00007f600a8a5000 4 4 4 r---- libpthread-2.17.so
00007f600a8a6000 4 4 4 rw--- libpthread-2.17.so
00007f600a8a7000 16 4 4 rw--- [ anon ]
00007f600a8ab000 84 12 0 r-x-- libgcc_s-4.8.5-20150702.so.1
00007f600a8c0000 2044 0 0 ----- libgcc_s-4.8.5-20150702.so.1
00007f600aabf000 4 4 4 r---- libgcc_s-4.8.5-20150702.so.1
00007f600aac0000 4 4 4 rw--- libgcc_s-4.8.5-20150702.so.1
00007f600aac1000 304 52 0 r-x-- libdw-0.172.so
00007f600ab0d000 2048 0 0 ----- libdw-0.172.so
00007f600ad0d000 8 8 8 r---- libdw-0.172.so
00007f600ad0f000 4 4 4 rw--- libdw-0.172.so
00007f600ad10000 16 8 0 r-x-- libgpg-error.so.0.10.0
00007f600ad14000 2044 0 0 ----- libgpg-error.so.0.10.0
00007f600af13000 4 4 4 r---- libgpg-error.so.0.10.0
00007f600af14000 4 4 4 rw--- libgpg-error.so.0.10.0
00007f600af15000 500 36 0 r-x-- libgcrypt.so.11.8.2
00007f600af92000 2044 0 0 ----- libgcrypt.so.11.8.2
00007f600b191000 4 4 4 r---- libgcrypt.so.11.8.2
00007f600b192000 12 12 12 rw--- libgcrypt.so.11.8.2
00007f600b195000 4 0 0 rw--- [ anon ]
00007f600b196000 80 12 0 r-x-- liblz4.so.1.7.5
00007f600b1aa000 2044 0 0 ----- liblz4.so.1.7.5
00007f600b3a9000 4 4 4 r---- liblz4.so.1.7.5
00007f600b3aa000 4 4 4 rw--- liblz4.so.1.7.5
00007f600b3ab000 148 16 0 r-x-- liblzma.so.5.2.2
00007f600b3d0000 2044 0 0 ----- liblzma.so.5.2.2
00007f600b5cf000 4 4 4 r---- liblzma.so.5.2.2
00007f600b5d0000 4 4 4 rw--- liblzma.so.5.2.2
00007f600b5d1000 28 16 0 r-x-- librt-2.17.so
00007f600b5d8000 2044 0 0 ----- librt-2.17.so
00007f600b7d7000 4 4 4 r---- librt-2.17.so
00007f600b7d8000 4 4 4 rw--- librt-2.17.so
00007f600b7d9000 1028 64 0 r-x-- libm-2.17.so
00007f600b8da000 2044 0 0 ----- libm-2.17.so
00007f600bad9000 4 4 4 r---- libm-2.17.so
00007f600bada000 4 4 4 rw--- libm-2.17.so
00007f600badb000 16 8 0 r-x-- libcap.so.2.22
00007f600badf000 2044 0 0 ----- libcap.so.2.22
00007f600bcde000 4 4 4 r---- libcap.so.2.22
00007f600bcdf000 4 4 4 rw--- libcap.so.2.22
00007f600bce0000 384 8 0 r-x-- libpcre.so.1.2.0
00007f600bd40000 2048 0 0 ----- libpcre.so.1.2.0
00007f600bf40000 4 4 4 r---- libpcre.so.1.2.0
00007f600bf41000 4 4 4 rw--- libpcre.so.1.2.0
00007f600bf42000 16 8 0 r-x-- libcap-ng.so.0.0.0
00007f600bf46000 2048 0 0 ----- libcap-ng.so.0.0.0
00007f600c146000 4 4 4 r---- libcap-ng.so.0.0.0
00007f600c147000 4 4 4 rw--- libcap-ng.so.0.0.0
00007f600c148000 88 20 0 r-x-- libnsl-2.17.so
00007f600c15e000 2048 0 0 ----- libnsl-2.17.so
00007f600c35e000 4 4 4 r---- libnsl-2.17.so
00007f600c35f000 4 4 4 rw--- libnsl-2.17.so
00007f600c360000 8 0 0 rw--- [ anon ]
00007f600c362000 1800 680 0 r-x-- libc-2.17.so
00007f600c524000 2048 0 0 ----- libc-2.17.so
00007f600c724000 16 16 16 r---- libc-2.17.so
00007f600c728000 8 8 8 rw--- libc-2.17.so
00007f600c72a000 20 20 20 rw--- [ anon ]
00007f600c72f000 12 8 0 r-x-- libcom_err.so.2.1
00007f600c732000 2044 0 0 ----- libcom_err.so.2.1
00007f600c931000 4 4 4 r---- libcom_err.so.2.1
00007f600c932000 4 4 4 rw--- libcom_err.so.2.1
00007f600c933000 100 24 0 r-x-- libk5crypto.so.3.1
00007f600c94c000 2044 0 0 ----- libk5crypto.so.3.1
00007f600cb4b000 8 8 8 r---- libk5crypto.so.3.1
00007f600cb4d000 4 4 4 rw--- libk5crypto.so.3.1
00007f600cb4e000 868 148 0 r-x-- libkrb5.so.3.3
00007f600cc27000 2044 0 0 ----- libkrb5.so.3.3
00007f600ce26000 56 56 56 r---- libkrb5.so.3.3
00007f600ce34000 12 12 12 rw--- libkrb5.so.3.3
00007f600ce37000 296 48 0 r-x-- libgssapi_krb5.so.2.2
00007f600ce81000 2048 0 0 ----- libgssapi_krb5.so.2.2
00007f600d081000 4 4 4 r---- libgssapi_krb5.so.2.2
00007f600d082000 8 8 8 rw--- libgssapi_krb5.so.2.2
00007f600d084000 88 16 0 r-x-- libresolv-2.17.so
00007f600d09a000 2044 0 0 ----- libresolv-2.17.so
00007f600d299000 4 4 4 r---- libresolv-2.17.so
00007f600d29a000 4 4 4 rw--- libresolv-2.17.so
00007f600d29b000 8 0 0 rw--- [ anon ]
00007f600d29d000 32 4 0 r-x-- libcrypt-2.17.so
00007f600d2a5000 2044 0 0 ----- libcrypt-2.17.so
00007f600d4a4000 4 4 4 r---- libcrypt-2.17.so
00007f600d4a5000 4 4 4 rw--- libcrypt-2.17.so
00007f600d4a6000 184 0 0 rw--- [ anon ]
00007f600d4d4000 84 12 0 r-x-- libz.so.1.2.7
00007f600d4e9000 2044 0 0 ----- libz.so.1.2.7
00007f600d6e8000 4 4 4 r---- libz.so.1.2.7
00007f600d6e9000 4 4 4 rw--- libz.so.1.2.7
00007f600d6ea000 8 4 0 r-x-- libutil-2.17.so
00007f600d6ec000 2044 0 0 ----- libutil-2.17.so
00007f600d8eb000 4 4 4 r---- libutil-2.17.so
00007f600d8ec000 4 4 4 rw--- libutil-2.17.so
00007f600d8ed000 56 16 0 r-x-- liblber-2.4.so.2.10.7
00007f600d8fb000 2044 0 0 ----- liblber-2.4.so.2.10.7
00007f600dafa000 4 4 4 r---- liblber-2.4.so.2.10.7
00007f600dafb000 4 4 4 rw--- liblber-2.4.so.2.10.7
00007f600dafc000 328 64 0 r-x-- libldap-2.4.so.2.10.7
00007f600db4e000 2048 0 0 ----- libldap-2.4.so.2.10.7
00007f600dd4e000 8 8 8 r---- libldap-2.4.so.2.10.7
00007f600dd50000 4 4 4 rw--- libldap-2.4.so.2.10.7
00007f600dd51000 8 8 0 r-x-- libdl-2.17.so
00007f600dd53000 2048 0 0 ----- libdl-2.17.so
00007f600df53000 4 4 4 r---- libdl-2.17.so
00007f600df54000 4 4 4 rw--- libdl-2.17.so
00007f600df55000 2256 916 0 r-x-- libcrypto.so.1.0.2k
00007f600e189000 2048 0 0 ----- libcrypto.so.1.0.2k
00007f600e389000 112 112 112 r---- libcrypto.so.1.0.2k
00007f600e3a5000 52 52 52 rw--- libcrypto.so.1.0.2k
00007f600e3b2000 16 8 8 rw--- [ anon ]
00007f600e3b6000 188 40 0 r-x-- libsystemd.so.0.6.0
00007f600e3e5000 2048 0 0 ----- libsystemd.so.0.6.0
00007f600e5e5000 4 4 4 r---- libsystemd.so.0.6.0
00007f600e5e6000 4 4 4 rw--- libsystemd.so.0.6.0
00007f600e5e7000 144 36 0 r-x-- libselinux.so.1
00007f600e60b000 2044 0 0 ----- libselinux.so.1
00007f600e80a000 4 4 4 r---- libselinux.so.1
00007f600e80b000 4 4 4 rw--- libselinux.so.1
00007f600e80c000 8 4 4 rw--- [ anon ]
00007f600e80e000 52 12 0 r-x-- libpam.so.0.83.1
00007f600e81b000 2048 0 0 ----- libpam.so.0.83.1
00007f600ea1b000 4 4 4 r---- libpam.so.0.83.1
00007f600ea1c000 4 4 4 rw--- libpam.so.0.83.1
00007f600ea1d000 120 16 0 r-x-- libaudit.so.1.0.0
00007f600ea3b000 2044 0 0 ----- libaudit.so.1.0.0
00007f600ec3a000 4 4 4 r---- libaudit.so.1.0.0
00007f600ec3b000 4 4 4 rw--- libaudit.so.1.0.0
00007f600ec3c000 40 0 0 rw--- [ anon ]
00007f600ec46000 36 16 0 r-x-- libwrap.so.0.7.6
00007f600ec4f000 2044 0 0 ----- libwrap.so.0.7.6
00007f600ee4e000 4 4 4 r---- libwrap.so.0.7.6
00007f600ee4f000 4 4 4 rw--- libwrap.so.0.7.6
00007f600ee50000 4 0 0 rw--- [ anon ]
00007f600ee51000 8 8 0 r-x-- libfipscheck.so.1.2.1
00007f600ee53000 2044 0 0 ----- libfipscheck.so.1.2.1
00007f600f052000 4 4 4 r---- libfipscheck.so.1.2.1
00007f600f053000 4 4 4 rw--- libfipscheck.so.1.2.1
00007f600f054000 136 120 0 r-x-- ld-2.17.so
00007f600f249000 92 92 92 rw--- [ anon ]
00007f600f274000 4 4 4 rw--- [ anon ]
00007f600f275000 4 4 4 r---- ld-2.17.so
00007f600f276000 4 4 4 rw--- ld-2.17.so
00007f600f277000 4 4 4 rw--- [ anon ]
00007ffe90ff6000 132 20 20 rw--- [ stack ]
00007ffe91019000 8 4 0 r-x-- [ anon ]
ffffffffff600000 4 0 0 r-x-- [ anon ]
---------------- ------- ------- -------
total kB 112760 4340 1024
可以看到该进程内存被哪些库、哪些文件所占用,据此我们定位程序对内存的使用。
几个字段介绍一下:
- Address:占用内存的文件的内存起始地址。
- Kbytes:占用内存的字节数。
- RSS:实际占用内存大小。
- Dirty:脏页大小。
- Mapping:占用内存的文件,[anon] 为已分配的内存,[stack] 为程序堆栈
最后的 total 为统计的总值。我们可以使用 pmap -x pid | tail -1 这样只显示最后一行,循环显示最后一行,达到监控该进程的目的。
[root@master ~]# while true; do pmap -x 7501 | tail -1; sleep 1; done
total kB 112760 4340 1024
total kB 112760 4340 1024
total kB 112760 4340 1024
total kB 112760 4340 1024
通过以上手段,我们基本上就能定位内存问题所在了,究竟是内存太小,还是进程占用内存太多,有哪些进程占用较多,这些进程又究竟有哪些地方占用较多,这些问题通过以上方法都能解决。
最后简单总结下,以上不少工具可能有人会犯选择困难症了。对于一般情况来说,查看系统内存用 free -h,分析进程内存占用用 ps 或者 top(首选 ps),深入分析选择 pmap,熟练运用这些就已经差不多了
后记
以上工具都是 Linux 自带的,当然还有很多高阶的工具,比如 atop、memstat 等等,对于内存泄漏有一个比较常用的检测工具 Valgrind