Linux 上怎么可能出现 OOM 场景(OOM 杀手背后的启发式方法)?

fic*_*ion 5 linux oom

我知道虚拟内存的概念。通过按需分页(取决于 vm.overcommit_memory),您可以分配比可用 RAM 更多的内存。除非您“触摸”页面,否则什么都不会发生。否则我猜有一个页面错误,然后物理内存被用于页面框架。但这在某种程度上意味着,如果系统内存紧张,它只会调出最近使用的内容并正常工作。

怎么可能需要终止一个进程呢?发生这种情况是因为 mlock() 处理了太多内存吗?垃圾过多后是否会调用 OOM?或者换个角度问:触发 OOM 杀手背后的启发到底是什么?

我读到您可以执行“echo 1 > memory.oom_control”或“echo -17 > /proc/PID/oom_adj”来禁用它。这意味着什么?机器可能会在一段时间内完全没有响应。但是,如果以某种方式,有问题的进程检测到它没有取得进展,它也可能暂时停止消耗内存(那么快),最终一切都应该重新开始工作,还是我错了?

在我的场景中,只有一个进程(具有巨大的内存缓存)。当然,该数据不是持久的,但我仍然不想重新启动该过程(并重新加载该数据)。

Wou*_*lst 5

您似乎对虚拟内存和过度使用之间的关系感到困惑。

物理内存由计算机中的 RAM 芯片组成。物理上不可能同时使用比物理内存更多的内存。然而,自 20 世纪 70 年代末以来,出现了虚拟内存,其中系统会将一些数据从物理内存移动到磁盘,从而存储实际上未使用的内存,以便物理内存可以用于其他用途。当这种情况发生时,程序无法立即使用被换出的数据;当他们尝试这样做时,处理器将生成页面错误,导致操作系统将所需的数据从交换区加载回物理内存。

通过使用虚拟内存,可以使用的传输数据总量扩展到物理内存加上交换空间的大小。虽然这允许系统同时运行更多程序,但实际使用的内存量永远不会超过可用虚拟内存总量(即 RAM + 交换空间)

原则上,内核应该跟踪程序向其请求的内存量,并且一旦其簿记告诉它所有内存已被分配,即使可能并非全部已被使用,它也应该拒绝对更多内存的请求。大多数其他内核都会这样做,因此它们没有 OOM 杀手(因为它们不需要)。

然而,程序从内核分配内存的系统调用并不是按字节分配内存;而是按字节分配内存。它通过更大的块来分配它。相比之下,大多数程序用于获取内存的实际实现(malloc()C 库函数)确实允许程序按字节分配内存。这意味着大多数程序在请求一些内存时最终会malloc()分配比实际需要的更多的内存。此外,一个好的malloc()实现会使用一些启发式方法将较小和较大的分配分开,这样内存碎片就不会太糟糕,但这样做需要它从内核请求更多内存,从而加剧了问题。由于这些和其他影响,在没有过度使用的情况下,将会有大量内存被分配但永远不会被使用。

过度使用的想法是,您可以安全地分配比系统可用虚拟内存总量更多的内存,而不会适得其反。本质上,内核声称它允许分配,即使它知道它无法兑现该承诺,因为假设它不需要兑现这些承诺的全部范围。然而,在不出现问题的情况下可以超额使用(分配)的确切数量是无法预测的;因此,当内核检测到程序正在尝试使用它们分配的所有内存时,内核将不得不食言。这就是 OOM 杀手发挥作用的地方。

这是否是一个好主意还有待争论。当系统内存不足时,就会出现问题如果这是某个应用程序试图分配更多内存但内核已经保留了所有内容的情况,那么该特定应用程序可能会崩溃。如果那恰好是您的 X 服务器,那么您就太倒霉了。至少如果有 OOM 杀手,它可以决定杀死哪个进程,而不是在分配错误后事情变得更糟;OOM 杀手有一些逻辑来避免杀死重要的进程,比如你的 X 服务器......

但是,如果您愿意,可以使用一些 sysctl 旋钮来关闭过度使用,如果您认为这是一个坏主意的话。

  • 理论上,虚拟内存受地址空间的限制,但实际上,它受物理内存和可用交换空间的限制。 (2认同)