为什么 Linux 内核上的程序使用的 vmem 比常驻内存多得多?

为什么 Linux 内核上的程序使用的 vmem 比常驻内存多得多?

与其他 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>/statshell 进程,VSZ = 580kB 和 RSS = 200kB(实际上是 50 页),但当然/proc/meminfo报告交换为零字节。也许top在这个 SBC 上运行可能会很有趣(因为我不知道top它的交换数字从哪里来)。

相关内容