如何在 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 使用者而言),而且反應不那麼快。

相關內容