当仍有大量物理内存未使用时,为什么 Linux 使用交换内存

当仍有大量物理内存未使用时,为什么 Linux 使用交换内存
root@host [/home4/nudenude/public_html/hello/cache]# top -r
        top: unknown argument 'r'
usage:  top -hv | -abcHimMsS -d delay -n iterations [-u user | -U user] -p pid [,pid ...]

root@host [/home4/nudenude/public_html/hello/cache]# top
top - 09:15:22 up 32 days,  7:12,  2 users,  load average: 274.18, 268.12, 262.50
Tasks: 863 total, 215 running, 630 sleeping,   3 stopped,  15 zombie
Cpu(s): 13.8%us, 85.7%sy,  0.4%ni,  0.0%id,  0.0%wa,  0.0%hi,  0.2%si,  0.0%st
Mem:  16313868k total,  7121660k used,  9192208k free,   679320k buffers
Swap:  4194296k total,   311896k used,  3882400k free,   478132k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
 6051 nudenude  20   0  103m  29m 4892 R  4.2  0.2   0:14.04 php
 6472 nudenude  20   0 97048  26m 5272 R  4.2  0.2   0:13.07 php
 7181 nudenude  20   0  100m  30m 4928 R  4.2  0.2   0:11.31 php
 7196 nudenude  20   0  105m  26m 5264 R  4.2  0.2   0:11.19 php
 8003 nudenude  20   0  105m  32m 5288 R  4.2  0.2   0:09.42 php
 8008 nudenude  20   0  107m  29m 4960 R  4.2  0.2   0:09.42 php
 8050 nudenude  20   0  105m  34m 5276 R  4.2  0.2   0:09.32 php
 8052 nudenude  20   0 98664  23m 5300 R  4.2  0.1   0:09.32 php
 8067 nudenude  20   0  104m  28m 5296 R  4.2  0.2   0:09.31 php
 8257 nudenude  20   0 96608  25m 5304 R  4.2  0.2   0:09.02 php
10640 nudenude  20   0 96032  22m 4932 R  4.2  0.1   0:04.40 php
12082 investgr  20   0 87588  16m 4928 R  4.2  0.1   0:00.23 php
 5962 nudenude  20   0  103m  33m 4900 R  3.9  0.2   0:14.19 php
 6095 nudenude  20   0  105m  29m 5276 R  3.9  0.2   0:13.96 php
 6467 nudenude  20   0  103m  28m 5280 R  3.9  0.2   0:12.97 php
 6488 nudenude  20   0  102m  26m 5280 R  3.9  0.2   0:12.96 php

我的服务器有 16 GB 内存。其中7GB仍然免费。而服务器使用4GB SWAP内存,85.7%的内存被系统使用。

为什么?还看专栏。 VIRT 103m,RES 29m。所以大多数记忆甚至不是物理的。为什么?

答案1

“VIRT 103m,RES 29m。所以大多数内存甚至都不是物理内存。为什么?”

既然让你注意到这种差异是我的错,我将尝试进一步解释。

如果您做过一些编程,您可能会知道什么是内存地址是——(通常)是系统用来组织内存字节的 32 或 64 位数字(因此,32 和 64 位计算机);内存的每个字节都有一个地址。如果您对此不熟悉,那么您现在需要了解的就是这些。

在现代操作系统上编程时遇到的地址在唯一性和引用 RAM 中特定唯一位置的意义上并不是“真实的”。换句话说,0xdeadbeef一个程序中的地址(即十六进制的 32 位数字,这通常是地址的表示方式)与其他程序中的 0xdeadbeef 的位置不同。曾几何时,他们是这样的;换句话说,系统只有一组地址,从 0x000000 开始,而这个地址空间在所有事物之间共享,包括内核。

现在情况不再如此的原因有很多,其中之一就是安全性。不同的程序不应该能够访问彼此的内存,因此它们没有理由需要地址。不管怎样,现在发生的是内核为每个进程提供了一个虚拟地址空间(也可以看看我对你另一个答案的回答) 从 0x0000000 开始。这是经过组织的,以便它的一部分映射到其他实体,例如共享库等。进程自己的私有空间被分为各个部分,其中大部分纯粹是理论上的——从技术上来说,它是“堆”部分的一部分,但是程序很少使用它们可用的整个堆。

顶部的 VIRT 分数取自内核通过 /proc 接口报告的数字。这是所有实际已被访问过的部分的所有地址致力于特定的事情。换句话说,它是程序的数量虚拟地址空间实际已经使用过的可用的。

那是仍然和真实的记忆不是一回事。 说你可能以某种特定的方式使用某物与使用它是不同的。例如,如果我声明一个 100 MB 的数组,但在数组中没有放置任何内容,我只是将 100MB 添加到我的 VIRT 分数中,但没有(或几乎没有,您需要一个字节来保存数组的地址)到 RSS/ RES(“RESident Set Size”)分数。内核非常聪明内存管理这边走。维护一个将虚拟地址映射到真实地址的表意味着虚拟地址列表可以比对应的真实地址列表大得多,因为很多虚拟地址不对应任何东西因为程序实际上并没有尝试访问它们——它只是要求创建它们。

当程序要访问尚未映射的地址时,内核会提供一些实际内存来执行此操作。因此,消耗的“虚拟地址空间”量将始终大于使用的“实际内存”量。通常它要大得多,但具体原因超出了本解释的范围;)

您可以将 VIRT 视为您安排的信用额度,将 RES 视为您的实际债务。由于 RES 包含可能与其他程序共享的部分(通常是公共库),因此这种类比变得复杂;这些部分是真实的,但它们的分数在访问它们的所有进程中都会重复。 Linux 内核报告“Pss”分数,例如:

  • 100%私人空间
  • 共享空间 A 的 25%,其中其他 3 个进程也使用 A。
  • 共享空间 B 的 50%,其中 1 个其他进程使用 B。

当使用 A 的其他进程之一结束时,您的 Pss 将相应上升(至 33%)。不过,Top 并未报告这一数字。

当仍有大量物理内存未使用时,为什么 Linux 使用交换内存

它与两个优先事项有关,这两个优先事项非常重视保留一些物理内存。在这种情况下,当东西被换出时,它属于仍在加载但已闲置很长时间的进程。如果/当它们再次使用时,它们将从交换区加载回物理内存(如有必要,交换其他内容)。

想要保留空闲内存池的第一个原因与上面讨论的内容有关;虽然银行(内核)发放的 WRT 内存信用额度可能比其一次性完成的额度要多得多,但很可能不需要这样做。然而,它可能必须在不久的将来实现其中的一部分。因此,我们的想法是,通过保留大量变化,可以使活动流程的响应速度更快;如果长时间空闲的进程留在 RAM 中直到完全满,则交换会变得更加明显,并且减慢最活跃进程的速度,因为直到达到临界点它才会发生。

另一个原因是空闲 RAM 实际上被内核用作文件缓存(这就是为什么第一行输出free通常与第二行有很大不同)。文件缓存的目的是将经常使用但当前未实际使用的内容保存在内存中,以备将来再次需要它们。当正在运行的进程完成某些操作时,它会被标记为可用内存,但会作为文件缓存的一部分保留在那里。如果那个或另一个进程再次请求该东西,它只是被标记为该进程的一部分(不再免费),这意味着它不必再次从磁盘加载。这还为活动进程提供了响应能力并提高了性能。

您可以通过调整分数来调整内核执行此策略的渴望程度/proc/sys/vm/swappiness。然而,除非您有特殊原因这样做,否则您应该保持原样——大量的思考和经验已经用于确定如何使系统在各种情况下保持最佳响应能力。

答案2

mmap'ed 文件也将显示为交换 [读取可交换或已交换]。

swapon -s 将告诉您交换的空间是否来自您配置的分页设备。如果不是,则可以肯定您的进程会附加到磁盘上的文件。

我认为程序可执行文件会以这种方式自动换出 - 因为程序已经在磁盘上,如果需要换出,可以从那里再次加载。不确定如果程序运行时可执行文件被覆盖会发生什么。

VIRT 包括从文件映射的页面、已使用的交换空间以及尚未物理分配的空间。 RES 是实际消耗的 RAM,但其中一部分与共享库重叠(例如,当共享每个共享对象的最后一个进程存在时,您只能取回 RES 下显示的全部数量。

paxdiablo 在这里对相关问题写了一个很好的答案:https://stackoverflow.com/questions/1972765/mmap-problem-allocates-huge-amounts-of-memory

干杯

相关内容