Como acionar ações em condições de pouca memória no Linux?

Como acionar ações em condições de pouca memória no Linux?

Então, pensei que isso seria algo muito simples de localizar: um módulo de serviço/kernel que, quando o kernel percebe que a memória do usuário está acabando, aciona alguma ação (por exemplo, despejar uma lista de processos em um arquivo, executar ping em algum endpoint da rede, o que for ) dentro de um processo que possui sua própria memória dedicada (para que não falhe no fork() ou sofra de qualquer outro problema comum de OOM).

Eu encontrei oAssassino de OOM, que eu entendo ser útil, mas que realmente não faz o que eu preciso fazer.

Idealmente, se estou ficando sem memória, quero saber por quê. Suponho que eu poderia escrever meu próprio programa que seja executado na inicialização e use uma quantidade fixa de memória, e só faça coisas quando for informado de pouca memória pelo kernel, mas isso levanta sua própria questão ...

Existe mesmo um syscall para ser informado de algo assim? Uma maneira de dizer ao kernel "ei, me acorde quando só temos 128 MB de memória"?

Pesquisei na web e aqui, mas não encontrei nada que se encaixe nessa descrição. Parece que a maioria das pessoas usa a pesquisa com atraso, mas o problema óbvio é que torna muito menos provável que você saiba quais processos causaram o problema.

Responder1

Sim, o kernel do Linux fornece um mecanismo para isso:notificação de pressão de memória. Isto está documentado emhttps://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt, seçãoPressão de memória.

Resumindo, você registra um descritor de arquivo eventfd no /sys/fs/cgroup/memory/memory.pressure_levelqual deseja receber notificações. Essas notificações podem ser low, mediumou critical. Um caso de uso típico seria liberar alguns ou todos os caches internos do seu processo ao receber uma notificação, para evitar uma interrupção iminente do OOM.

Responder2

O que você está perguntando é, basicamente, um retorno de chamada baseado em kernel em uma condição de pouca memória, certo? Se assim for, acredito fortemente que o kernel nãonãofornecer tal mecanismo,E por uma boa razão:estando com pouca memória, ele deve executar imediatamente a única coisa que pode liberar memória - o OOM killer. Quaisquer outros programas podem parar a máquina.

De qualquer forma, você pode executar uma solução simples de monitoramento no espaço do usuário. Eu tinha o mesmo requisito de depuração/ação com pouca memória no passado e escrevi um bash simples que fazia o seguinte:

  • monitorar por ummarca d’água suave:se o uso de memória estiver acima deste limite, colete algumas estatísticas (processos, memória livre/utilizada, etc) e envie um email de aviso;

  • monitorar por ummarca d'água dura:se o uso de memória estiver acima desse limite, colete algumas estatísticas e elimine os processos que consomem mais memória (ou menos importantes) e, em seguida, envie um e-mail de alerta.

Esse script seria muito leve e pode pesquisar a máquina em pequenos intervalos (ou seja: 15 segundos)

Responder3

A melhor resposta atual é para cgroups-v1. Para cgroups-v2, pode-se ouvir eventos modificados de arquivo no memory.eventsarquivo (documentaçãodo conteúdo do arquivo).

O comportamento deste arquivo pode ser testado com alguns comandos 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

Infelizmente, isso parece funcionar apenas se houver um limite de memória definido para o cgroup. Como alternativa, pode-seouça a memória.pressão, mas não é baseado em cgroup (pelo menos para usuários não-root) e não tem reação tão rápida.

informação relacionada