如何在 Linux 内存不足的情况下触发操作?

如何在 Linux 内存不足的情况下触发操作?

所以,我认为这将是一个非常简单的定位:一个服务/内核模块,当内核注意到用户态内存不足时,会触发一些操作(例如将进程列表转储到文件,ping某些网络端点,等等) )在拥有自己的专用内存的进程中(因此它不会无法 fork() 或遭受任何其他常见的 OOM 问题)。

我找到了OOM 杀手,我知道这是有用的,但它并没有真正做我需要做的事情。

理想情况下,如果我的内存不足,我想知道原因。我想我可以编写自己的程序,该程序在启动时运行并使用固定数量的内存,然后只有在内核通知内存不足时才执行操作,但这会带来自己的问题......

是否有一个系统调用可以通知类似的事情?一种对内核说“嘿,当我们只剩下 128 MB 内存时叫醒我”的方式?

我在网上和这里搜索,但没有找到任何符合该描述的内容。似乎大多数人都在时间延迟上使用轮询,但明显的问题是,它使您不太可能知道哪个进程导致了问题。

答案1

是的,Linux 内核确实为此提供了一种机制:内存压力通知。这记录在https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt, 部分内存压力

简而言之,您注册一个/sys/fs/cgroup/memory/memory.pressure_level要在其中接收通知的 eventfd 文件描述符。这些通知可以是lowmedium、 或critical。典型的用例是在收到通知时释放进程中的部分或全部内部缓存,以防止即将发生的 OOM 终止。

答案2

您所要求的基本上是在内存不足的情况下基于内核的回调,对吧?如果是这样,我坚信内核确实不是提供这样的机制,并且有充分的理由:由于内存不足,它应该立即运行唯一可以释放内存的东西 - OOM 杀手。任何其他程序都可能使机器停止运行。

无论如何,您可以在用户空间中运行一个简单的监控解决方案。我过去有同样的低内存调试/操作要求,我编写了一个简单的 bash,它执行以下操作:

  • 监视一个软水印:如果内存使用量高于此阈值,则收集一些统计信息(进程、可用/已用内存等)并发送警告电子邮件;

  • 监视硬水印:如果内存使用量高于此阈值,请收集一些统计信息并终止更多内存消耗(或不太重要)的进程,然后发送警报电子邮件。

这样的脚本会非常轻量级,并且它可以以很小的间隔(即:15秒)轮询机器

答案3

当前的最佳答案是 cgroups-v1。对于 cgroups-v2,可以监听memory.events文件上的文件修改事件(文档文件内容)。

实际上可以使用一些 shell 命令来测试该文件的行为:

# Spawn a new slice with memory limits to avoid OOMing the entire system
systemd-run --pty --user -p MemoryMax=1050M -p MemoryHigh=1000M bash

# Watch memory.events for changes and read when changed
inotifywait -e modify -m /sys/fs/cgroup$(cut -d: -f3 /proc/self/cgroup)/memory.events \
  | while read l; do echo $l; cat ${l// *}; done &
# Consume memory
tail /dev/zero

遗憾的是,这似乎只有在确实为 cgroup 设置了内存限制的情况下才有效。作为一种替代方案,人们可​​以听记忆压力,但这不是基于 cgroup 的(至少对于非 root 用户而言),并且反应不那么快。

相关内容