Linux中的过程内存管理
1. 概述
在本教程中,我们将探讨 Linux 中进程使用的四种内存测量方法;VSZ、RSS、USS 和 PSS。 每个都有自己的特点和用法,我们将在详细介绍时看到。
2. VSZ内存
VSZ 是虚拟内存大小的缩写。它是一个进程可以假设访问的内存总量。
它说明了二进制文件本身、任何链接库以及任何堆栈或堆分配的大小。
当一个进程启动时,VSZ 内存变成了 RSS 内存,我们现在就来看看。
3.RSS记忆
与 VSZ 不同,RSS 也是 Resident Set Size 的缩写,它是一种度量,用于显示在进程执行期间分配给进程的 RAM 量。
但是,它实际上并不是对进程 RAM 使用情况的准确测量,因为它没有考虑已加载到内存中的库。
如果两个进程使用一个或多个库,那么 RSS 将报告每个进程的库大小,即使在一个进程接着另一个进程启动的情况下已经预先加载了库。这就是为什么 RSS 可能具有误导性并且不应该完全被信任的原因。
因为 RSS 显示整个内存输出,即使是已经预加载的信息,如果我们将进程列表中的所有内容加起来,我们将获得比分配的总内存更多的内存。
4. 使用RSS和VSZ
4.1. 使用ps
检查 Linux 进程的 RSS 和 VSZ 的方法之一是调用ps :
$ ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.1 0.0 169316 13184 ? Ss 18:14 0:04 /sbin/init splash
root 2 0.0 0.0 0 0 ? S 18:14 0:00 [kthreadd]
root 3 0.0 0.0 0 0 ? I< 18:14 0:00 [rcu_gp]
// ...
root 28 0.0 0.0 0 0 ? S 18:14 0:00 [idle_inject/3]
上面的输出只是终端中列出的所有进程的一小部分。
但正如我们所见,我们有两个名为 RSS 和 VSZ 的列,它们显示分配给每个进程的总内存和进程分配给自己的最大值。
如果我们只想查看某些进程(例如所有 Google Chrome 进程),我们可以使用:
ps eo user,pid,vsz,rss $(pgrep -f 'chrome')
USER PID VSZ RSS
blogdemo-reader 5236 1358620 333984
blogdemo-reader 5246 268300 63804
blogdemo-reader 5247 268300 63084
// ...
blogdemo-reader 36354 4587872 52700
4.2. 使用top
另一个检查进程的有用命令是top 。当我们使用它时,它会显示我们系统中运行的所有进程。 与上面的命令不同,它每次都会检查正在运行的进程列表中的变化,因此我们可以实时看到 RSS 和 VSZ 的变化。
例如,如果我们查看 PID 为 12408 的进程(在本例中为 google chrome 实例),我们可以看到例如 %CPU 的差异,它显示了该特定进程正在使用多少 CPU。正如我们在终端中看到的那样,有多个 chrome 进程在运行,这是有道理的,因为确实有多个进程在运行——实际的 chrome 应用程序、打开的选项卡、可能通过浏览器下载器进行的一些下载等——它们是在 CPU 认为合适的情况下分配更多或更少的资源:
top - 22:55:50 up 4:41, 1 user, load average: 0,82, 2,25, 2,72
Tasks: 350 total, 1 running, 349 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0,5 us, 0,2 sy, 0,0 ni, 99,3 id, 0,0 wa, 0,0 hi, 0,0 si, 0,0 st
MiB Mem : 32035,2 total, 23820,8 free, 3484,8 used, 4729,7 buff/cache
MiB Swap: 0,0 total, 0,0 free, 0,0 used. 27832,6 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
// ...
12408 blogdemo-reader 20 0 9146156 312452 119532 S 1,7 1,0 9:56.70 chrome
// ...
12077 blogdemo-reader 20 0 4784576 182196 92716 S 0,3 0,6 1:00.59 chrome
30 秒后:
top - 22:56:20 up 4:41, 1 user, load average: 0,63, 2,07, 2,65
Tasks: 351 total, 1 running, 350 sleeping, 0 stopped, 0 zombie
%Cpu(s): 1,8 us, 0,5 sy, 0,0 ni, 97,7 id, 0,0 wa, 0,0 hi, 0,0 si, 0,0 st
MiB Mem : 32035,2 total, 23806,6 free, 3492,9 used, 4735,7 buff/cache
MiB Swap: 0,0 total, 0,0 free, 0,0 used. 27819,3 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
// ...
12408 blogdemo-reader 20 0 9185940 306080 123896 S 14,0 0,9 10:00.01 chrome
// ...
4340 blogdemo-reader 20 0 1171680 328412 156400 S 1,3 1,0 6:15.76 chrome
// ...
4579 blogdemo-reader 20 0 4723180 172064 73352 S 0,7 0,5 0:23.38 chrome
// ...
4414 blogdemo-reader 20 0 377528 105756 66972 S 0,3 0,3 1:33.44 chrome
4457 blogdemo-reader 20 0 431860 120172 86228 S 0,3 0,4 20:52.63 chrome
12691 blogdemo-reader 20 0 4737484 173728 99572 S 0,3 0,5 0:15.66 chrome
// ...
同样,这只是输出的一小部分,但我们可以看到变化的波动性以及 CPU 排序的进程,这些进程被优先化和非优先化。
正如我们之前提到的,这些类型并不完全准确,但我们可以得到一个可靠的估计。
5. PSS内存
PSS 或 Proportional Set Size 是一种更有用的内存管理指标。它的工作方式与 RSS 完全相同,但增加了对共享库进行分区的区别。
例如,如果我们有五个进程使用相同的库,大小为 50 页,对于每个进程,PSS 报告的大小将只有 10 页用于该特定共享库。所有共享进程的所有共享库都会发生同样的事情。
PSS 的一个优点是将所有进程加在一起,我们可以很好地估计系统中的整个内存使用情况。
6. USS 内存
**唯一集大小或 USS 表示进程的私有内存。**换句话说,它显示了只分配给这个进程的库和页面。
这种类型的内存也非常有用,因为它代表了启动另一个进程的实际成本。反之亦然,当一个流程结束时,它代表返回给系统的实际金额。
7. 使用 PSS 和 USS
7.1. 使用ps
要检查 Linux 进程上的 PSS 内存,我们必须访问要检查的进程的*/proc/{$PID}/smaps*。为此,我们需要我们要检查的进程的 PID。
例如,如果我们要检查rabbitmq-server进程:
$ ps -aux | grep 'rabbitmq-server'
rabbitmq 1055 0.0 0.0 2608 604 ? Ss iun04 0:00 /bin/sh /usr/sbin/rabbitmq-server
$ sudo cat /proc/1055/smaps | grep -w 'Pss:'
Pss: 20 kB
Pss: 76 kB
Pss: 24 kB
// ...
Pss: 0 kB
在这里,我们将看到多个 PSS 输出,如果我们将它们相加,我们将获得该过程的总 PSS 打印。或者,我们可以这样做,而不是添加大量数字:
$ sudo cat /proc/1055/smaps | grep -i 'Pss:' | awk '{Total+=$2} END {print Total}'
165
在这里,我们以 KB 为单位报告了rabbitmq-server进程的总 PSS 内存大小。如果我们有一个使用大量 PSS 内存的进程,我们可以格式化输出以以更大的度量单位报告它:
$ sudo cat /proc/1055/smaps | grep -i 'Pss:' | awk '{Total+=$2} END {print Total/1000" MB"}'
0,165 MB
我们只需要记住除以 1000,而不是 1024,因为这是 Kilo 和 Mega 之间的差异。
7.2. 使用smem
我们用来检查 USS 的一个非常有趣的工具是smem ,我们用它来输出 USS 和其他类型:
$ sudo apt-get install smem
$ smem
PID User Command Swap USS PSS RSS
4346 blogdemo-reader cat 0 116 149 1936
4347 blogdemo-reader cat 0 120 151 1884
2663 blogdemo-reader /usr/libexec/gnome-session- 0 488 522 5240
2578 blogdemo-reader /usr/libexec/xdg-permission 0 748 794 6320
2558 blogdemo-reader /usr/bin/dbus-daemon --conf 0 668 812 4672
2820 blogdemo-reader /usr/libexec/gsd-screensave 0 788 832 6404
2531 blogdemo-reader /usr/libexec/ibus-memconf 0 776 859 7148
2803 blogdemo-reader /usr/libexec/gsd-a11y-setti 0 832 885 6728
2551 blogdemo-reader /usr/libexec/at-spi-bus-lau 0 824 893 7284
3192 blogdemo-reader /usr/libexec/gvfsd-metadata 0 860 902 6376
2498 blogdemo-reader /usr/libexec/gvfs-mtp-volum 0 860 906 6544
2431 blogdemo-reader /usr/libexec/gvfs-goa-volum 0 904 990 6644
为了检查某个进程,我们再次使用grep 命令:
$ smem | grep -w 'chrome'
60608 ioan grep --color=auto -w chrome 0 364 396 2588
4381 ioan /opt/google/chrome/nacl_hel 0 604 1121 4132
4376 ioan /opt/google/chrome/nacl_hel 0 668 1183 4204
4379 ioan /opt/google/chrome/chrome - 0 204 1232 15752
// ...
4340 ioan /opt/google/chrome/chrome 0 276260 290467 387636