Eu estava executando um shell script com comandos para executar vários programas com muita memória (2 a 5 GB) consecutivos. Quando voltei para verificar o andamento do meu script, fiquei surpreso ao descobrir que alguns dos meus processos eram Killed
, como meu terminal me informou. Vários programas já foram concluídos sucessivamente antes dos programas que foram Killed
iniciados posteriormente , mas todos os programas posteriormente falharam em uma falha de segmentação (que pode ou não ter sido devido a um bug no meu código, continue lendo).
Examinei o histórico de uso do cluster específico que estava usando e vi que alguém começou a executar vários processos com muita memória ao mesmo tempo e, ao fazê-lo, esgotou a memória real (e possivelmente até o espaço de troca) disponível para o cluster. Pelo melhor que pude imaginar, esses processos com muita memória começaram a ser executados na mesma época em que comecei a ter problemas com meus programas.
É possível que o Linux tenha matado meus programas quando começou a ficar sem memória? E é possível que as falhas de segmentação que obtive mais tarde sejam devidas à falta de memória disponível para executar meus programas (em vez de um erro no meu código)?
fonte
Respostas:
Pode.
Existem duas condições diferentes de falta de memória que você pode encontrar no Linux. O que você encontra depende do valor de
sysctl vm.overcommit_memory
(/proc/sys/vm/overcommit_memory
)Introdução:
O kernel pode executar o que é chamado de 'supercomprometimento de memória'. É quando o kernel aloca programas mais memória do que realmente está presente no sistema. Isso é feito na esperança de que os programas não usem toda a memória que eles alocaram, pois essa é uma ocorrência bastante comum.
overcommit_memory = 2
Quando
overcommit_memory
está definido como2
, o kernel não executa nenhuma confirmação excessiva. Em vez disso, quando um programa recebe memória, é garantido o acesso a essa memória. Se o sistema não tiver memória livre suficiente para satisfazer uma solicitação de alocação, o kernel retornará apenas uma falha para a solicitação. Cabe ao programa lidar normalmente com a situação. Se não verificar se a alocação foi bem-sucedida quando realmente falhou, o aplicativo geralmente encontrará um segfault.No caso do segfault, você deve encontrar uma linha como esta na saída de
dmesg
:Os
at 0
meios que o aplicativo tentou acessar um ponteiro não inicializado, que pode ser o resultado de uma falha na chamada de alocação de memória (mas não é a única maneira).overcommit_memory = 0 e 1
Quando
overcommit_memory
está definido como0
ou1
, a confirmação excessiva é ativada e os programas têm permissão para alocar mais memória do que realmente está disponível.No entanto, quando um programa deseja usar a memória que foi alocada, mas o kernel descobre que na verdade não possui memória suficiente para satisfazê-lo, ele precisa recuperar alguma memória. Primeiro, ele tenta executar várias tarefas de limpeza de memória, como a limpeza de caches, mas se isso não for suficiente, encerrará um processo. Essa terminação é realizada pelo OOM-Killer. O OOM-Killer analisa o sistema para ver quais programas estão usando qual memória, há quanto tempo eles estão sendo executados, quem os executa e vários outros fatores para determinar qual deles é morto.
Depois que o processo é encerrado, a memória usada é liberada e o programa que acabou de causar a condição de falta de memória agora tem a memória necessária.
No entanto, mesmo nesse modo, os programas ainda podem receber pedidos de alocação negados. Quando
overcommit_memory
é0
, o kernel tenta adivinhar quando deve começar a negar solicitações de alocação. Quando está definido como1
, não tenho certeza de qual determinação ele usa para determinar quando deve negar uma solicitação, mas pode negar solicitações muito grandes.Você pode ver se o OOM-Killer está envolvido observando a saída de
dmesg
e localizando mensagens como:fonte
overcommit_memory
é definido como 0 ou 2.overcommit_memory=2
o assassino de OOM não estiver ativado, então controlá-lo é irrelevante. No entanto, uma vez que estabelecemos que é o assassino da OOM, isso se torna outro assunto, abrangido por muitas outras perguntas e respostas aqui.A verdade é que, independentemente de como você olha para ele - se seu processo foi interrompido devido ao gerenciador de memória do sistema ou devido a alguma outra coisa - ainda é um bug. O que aconteceu com todos esses dados que você estava apenas processando na memória? Deveria ter sido salvo.
Embora
overcommit_memory=
seja a maneira mais geral de configurar o gerenciamento do Linux OOM, também é ajustável por processo, como:O uso
-17
do procedimento acima excluirá um processo do gerenciamento de falta de memória. Provavelmente não é uma boa ideia em geral, mas se você estiver caçando bugs, pode valer a pena - especialmente se você deseja saber se era OOM ou seu código. Aumentar positivamente o número aumentará a probabilidade de morte do processo em um evento de OOM, o que poderá permitir uma melhor resiliência do seu código em situações de pouca memória e garantir que você saia normalmente quando necessário.Você pode verificar as configurações atuais do manipulador de OOM por processo, como:
Caso contrário, você poderia se suicidar:
Isso configurará o computador para reiniciar no caso de uma condição de falta de memória. Você define o
X
número acima para o número de segundos que deseja que o computador pare após um pânico no kernel antes de reiniciar. Enlouquecer.E se, por algum motivo, você decidir que gosta, torne-o persistente:
fonte