Gerência de Memória em Sistemas Linux: Ocorrencias quando a Memória Está Esgotada

Gerência de Memória em Sistemas Linux: Ocorrencias quando a Memória Está Esgotada

Este artigo explora o que acontece em um sistema Linux quando a memória física está esgotada, abordando os mecanismos de gerenciamento de memória e suas implicações de desempenho.

Processo de Alocação de Memória

Quando um aplicativo solicita memória através da função malloc, na verdade está solicitando memória virtual. Nesse momento, nenhuma memória física é alocada imediatamente.

Quando o aplicativo acessa essa memória virtual, o CPU tenta acessá-la e descobre que não há mapeamento com memória física. Isso aciona uma interrupção de página ausente, fazendo com que o processo mude do modo usuário para o modo kernel. O manipulador de interrupção de página ausente do kernel verifica se há memória física disponível.

Se houver memória física livre, ela é alocada e estabelece-se o mapeamento entre memória virtual e memória física. Caso contrário, o kernel inicia o processo de recuperação de memória, que pode ocorrer de duas formas:

  • Recuperação de memória em segundo plano (kswapd): Quando a memória física está tensionada, o kernel thread kswapd é acionado para recuperar memória de forma assíncrona, sem bloquear a execução do processo.
  • Recuperação de memória direta: Se a recuperação assíncrona não acompanhar a velocidade de solicitação de memória dos processos, inicia-se uma recuperação síncrona que bloqueia a execução do processo.

Se mesmo após a recuperação direta não houver memória física suficiente para a solicitação atual, o kernel recorre a sua última opção: acionar o mecanismo OOM (Out of Memory). O OOM Killer seleciona um processo que consome muita memória e o encerra para liberar recursos. Se a memória ainda for insuficiente, o processo continua sendo selecionado até que haja memória suficiente.

Quais Tipos de Memória Podem ser Recuperados?

Quando a memória do sistema está tensionada, o kernel pode recuperar dois tipos principais de memória:

  • Páginas de arquivo: São dados de arquivos cacheados pelo kernel. A maioria pode ser liberada diretamente, pois pode ser relida do disco quando necessário. Páginas modificadas (sujas) devem ser gravadas no disco antes da liberação.
  • Páginas anônimas: São alocadas dinamicamente por aplicativos através de mmap. Essas páginas não podem ser liberadas diretamente e são recuperadas através do mecanismo Swap do Linux, que move páginas pouco acessadas para o disco.

A recuperação de ambos os tipos de página segue o algoritmo LRU (Least Recent Used), priorizando páginas menos acessadas. O sistema mantém duas listas duplamente ligadas:

  • active_list: Armazena páginas recentemente acessadas.
  • inactive_list: Armazena páginas raramente acessadas.

As páginas mais próximas do final das listas são as menos acessadas e são priorizadas para recuperação.

Impacto no Desempenho da Recuperação de Memória

A recuperação de memória pode afetar significativamente o desempenho do sistema:

  • Recuperação de páginas de arquivo: Páginas limpas são liberadas diretamente sem impacto, enquanto páginas sujas exigem operações de I/O no disco.
  • Recuperação de páginas aônimas: O mecanismo Swap realiza operações de leitura/escrita no disco quando páginas são movidas para e do espaço de swap.

Operações frequentes de recuperação de memória resultam em múltiplas operações de I/O, degradando o desempenho do sistema.

Soluções para Mitigar Impactos de Desempenho

  1. Ajuste da tendência de recuperação de páginasO Linux oferece a opção /proc/sys/vm/swappiness para ajustar a preferência entre recuperação de páginas de arquivo e anônimas. Um valor entre 0-100, onde valores maiores favorecem o uso de Swap (recuperação de páginas anônimas).

    # Verificar valor atual de swappiness
    $ cat /proc/sys/vm/swappiness
    

    Valores menores (como 0) priorizam a recuperação de páginas de arquivo.

  2. Acionar antecipadamente a recuperação assíncronaO kernel define três limiares de memória para determinar quando acionar a recuperação:

    • pages_min: Limiar mínimo
    • pages_low: Limiar baixo
    • pages_high: Limiar alto

    Quando a memória livre está entre pages_low e pages_min, o kswapd inicia recuperação assíncrona. Quando a memória está abaixo de pages_min, inicia-se recuperação direta.

    O limiar baixo pode ser ajustado indiretamente através de /proc/sys/vm/min_free_kbytes:

    # Relação entre os limiares
    pages_min = min_free_kbytes
    pages_low = pages_min * 5/4
    pages_high = pages_min * 3/2
    

    Aumentar min_free_kbytes aciona a recuperação assíncrona mais cedo, evitando recuperação direta, mas reduz a memória disponível para aplicativos.

  3. Estratégia de recuperação em arquitetura NUMAEm sistemas NUMA (Non-Uniform Memory Access), cada nó tem memória local. O modo de recuperação é controlado por /proc/sys/vm/zone_reclaim_mode:

    0 (padrão): Procurar memória livre em outros nós antes de recuperar localmente
    1: Recuperar apenas memória local
    2: Recuperar memória local, incluindo escrita de páginas sujas
    4: Recuperar memória local usando Swap
    

    Recomenda-se manter o valor 0 para evitar recuperação prematura quando há memória disponível em outros nós.

Proteção de Processos contra o OOM Killer

Quando a memória está esgotada e a recuperação direta não é suficiente, o OOM Killer seleciona processos para encerrar baseado na função oom_badness():

points = process_pages + oom_score_adj * totalpages / 1000

Onde:

  • process_pages: Número de páginas físicas usadas pelo processo
  • oom_score_adj: Valor de ajuste do OOM (-1000 a 1000)
  • totalpages: Número total de páginas disponíveis no sistema

O valor de oom_score_adj pode ser ajustado para /proc/[pid]/oom_score_adj:

  • -1000: Protege o processo contra OOM
  • 0: Padrão
  • 1000: Máxima probabilidade de ser selecionado

Processos críticos como sshd devem ter oom_score_adj = -1000. Para aplicativos de negócio, é melhor não definir -1000 para permitir que processos com vazamento de memória sejam encerrados.

Tags: gerenciamento de memória Linux kernel swap lru

Publicado em 6-12 04:26 por Thomas