与其他 UNIX 风格的操作系统不同,Linux 进程通常会消耗无意义的 vmem(与常驻内存相比)。
例如在我的笔记本电脑上
plugin-container 使用的 vsz 比 rss 多 20 倍,lxterminal 使用的 vss 比 rss 多 40 倍
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
petanb 2036 1.7 39.8 2027260 743108 ? Sl Jul01 260:16 /usr/lib/firefox/firefox
petanb 2170 3.4 1.8 668460 33716 ? Sl Jul01 520:11 /usr/lib/firefox/plugin-container /usr/lib/flashplugin-installer/libflashplayer.so -gr
petanb 2391 0.0 0.7 698888 14080 ? Dl Jul01 7:02 /usr/bin/lxterminal
petanb 4633 0.0 0.4 430568 8816 ? Sl Jul01 0:08 /usr/lib/notify-osd/notify-osd
看看 VSZ 和 RSS 之间的区别,为什么会这样?我知道虚拟内存比常驻内存大,但为什么大这么多?
答案1
首先,程序/进程不会“吃掉”内存。它们使用或被分配内存。
比斯开(虚拟内存大小,单位为千字节)是进程所需的所有虚拟内存的总和。此大小主要是进程/程序的属性,而不是操作系统的控制。
RSS是驻留集大小,即分配给进程的物理内存量。这是用于保存进程执行期间驻留(而不是位于后备存储中,即交换出去)的虚拟内存页面的物理内存。RSS 将小于或等于进程的虚拟内存大小。
请注意,有时 RSS 被报告为页面数(通常大小为 4096 字节),而不是千字节。因此在这些情况下,将 VSZ 与 RSS 进行比较是不合适的。
请注意,该过程的这两种规模都可能包括共享库以及用于代码/文本、数据、堆和堆栈的内存。操作系统负责调度进程,并确定进程的哪些页面驻留在(物理)内存中,哪些页面被换出。共享库比进程专用的页面更有可能保持驻留。处于休眠状态的进程(例如 STAT == D1 或 STAT == S1)可能会将其大部分页面换出,并具有较小的 RSS。这一切都在操作系统和进程执行动态的控制之下。
还要注意的是,Linux 与大多数其他 *nix 不同,Linux(除非另有配置)将过度承诺请求(虚拟)内存。因此,即使没有为进程分配页面框架或交换空间(直到进程尝试访问此“已分配”内存),其 VSS 仍会增加。
附录:回复评论
为什么差别这么大?有时 VSZ 比 RSS 大 20 倍,即使在没有交换的系统上也是如此。
您引用了一个特定的例子,但没有提供任何细节。
如果没有交换,Linux 的过度提交功能可能是 VSZ 和 RSS 之间出现巨大差异的一个因素。该程序是否malloc()
对大但未使用的缓冲区执行操作?
也许您必须使用诸如pmap
和之类的内存工具自己评估该进程的内存使用情况top
,这将提供更多细节。
看“运行时内存测量”有关一些信息。top
文档声明
SWAP -- Swapped size (kb)
The swapped out portion of a task's total virtual memory image.
RES -- Resident size (kb)
The non-swapped physical memory a task has used.
RES = CODE + DATA.
VIRT -- Virtual Image (kb)
The total amount of virtual memory used by the task. It includes all code, data and shared libraries plus pages that have been swapped out.
VIRT = SWAP + RES
我不知道这些top
定义是否应该考虑已提交但尚未分配物理资源的虚拟内存。我认为应该考虑,但 VIRT 方程通过省略已提交但尚未分配虚拟内存的(不常见)情况而得到简化。
附录2:回复评论
也许尝试在您自己的计算机上运行 top 或 htop,您将看到有许多进程使用了大量 VSZ 并且几乎不使用 RSS
在我的 Ubuntu 系统上没有看到任何有趣的东西:
PID PR NI VIRT RES SHR S %CPU %MEM SWAP CODE DATA nDRT COMMAND
26379 20 0 20812 7996 3496 S 4 0.4 12m 4 2828 0 gs
1082 20 0 85292 46m 15m S 2 2.5 36m 1660 30m 0 Xorg
2036 20 0 22948 8756 7148 S 1 0.4 13m 40 788 0 multiload-apple
2411 20 0 47984 19m 10m S 1 1.0 27m 1924 7584 0 python
62 20 0 0 0 0 S 0 0.0 0 0 0 0 kondemand/0
930 20 0 3236 1528 792 S 0 0.1 1708 284 820 0 dbus-daemon
1618 20 0 6964 3084 2244 S 0 0.2 3880 420 836 0 cupsd
1971 20 0 15708 3100 2484 S 0 0.2 12m 216 10m 0 udisks-daemon
2037 20 0 39316 11m 9676 S 0 0.6 26m 76 1404 0 sensors-applet
25733 20 0 2568 1280 956 R 0 0.1 1288 64 480 0 top
2473 20 0 6712 4060 1564 S 0 0.2 2652 780 2492 0 bash
对于所有的用户进程来说,VIRT == SWAP + RES
都是正确的,但RES == CODE + DATA
事实并非如此。
我确实有几个运行嵌入式 Linux 的 SBC,但没有top
为它们进行交叉编译。查看/proc/<pid>/stat
shell 进程,VSZ = 580kB 和 RSS = 200kB(实际上是 50 页),但当然/proc/meminfo
报告交换为零字节。也许top
在这个 SBC 上运行可能会很有趣(因为我不知道top
它的交换数字从哪里来)。