Linux에서 메모리 부족 상태에서 작업을 트리거하는 방법은 무엇입니까?

Linux에서 메모리 부족 상태에서 작업을 트리거하는 방법은 무엇입니까?

그래서 저는 이것이 찾기 매우 간단할 것이라고 생각했습니다: 커널이 사용자 영역 메모리가 부족하다는 것을 알아차렸을 때 일부 작업(예: 프로세스 목록을 파일에 덤프, 일부 네트워크 엔드포인트에 핑을 보내는 등)을 트리거하는 서비스/커널 모듈입니다. ) 자체 전용 메모리가 있는 프로세스 내에서 수행됩니다(따라서 fork()에 실패하거나 다른 일반적인 OOM 문제가 발생하지 않습니다).

나는 찾았다OOM 킬러, 유용하다고 이해하지만 실제로 해야 할 작업을 수행하지는 않습니다.

이상적으로는 메모리가 부족한 경우 그 이유를 알고 싶습니다. 시작 시 실행되고 고정된 양의 메모리를 사용하며 커널에서 메모리 부족에 대한 알림을 받은 후에만 작업을 수행하는 자체 프로그램을 작성할 수 있다고 가정합니다. 하지만 그러면 자체적인 질문이 발생합니다...

그런 정보를 받을 수 있는 시스템콜도 있나요? 커널에 "128MB의 메모리만 남았을 때 깨워주세요"라고 말하는 방법은 무엇입니까?

웹과 여기에서 검색했지만 해당 설명에 맞는 항목을 찾지 못했습니다. 대부분의 사람들이 시간 지연에 대해 폴링을 사용하는 것처럼 보이지만, 이에 대한 명백한 문제는 어떤 프로세스가 문제를 일으켰는지 알 가능성이 훨씬 적다는 것입니다.

답변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(선적 서류 비치파일 내용).

이 파일의 동작은 실제로 몇 가지 셸 명령을 사용하여 테스트할 수 있습니다.

# 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 기반이 아니며(적어도 루트가 아닌 사용자의 경우) 빠르게 반응하지 않습니다.

관련 정보