Gestão de memória do Linux: Swap, OOM Killer & Cgroups
12 min de leitura - 31 de maio de 2026

Como o Linux swap, o OOM killer e o cgroups funcionam em conjunto - com exemplos de configuração para bases de dados, servidores Web e hosts VPS multi-tenant.
Explicação sobre a gestão de memória no Linux: swap, OOM killer e cgroups
O Linux lida com a memória de forma diferente da maioria dos sistemas operativos. Um elevado consumo de RAM nem sempre é um problema — o kernel utiliza ativamente a memória livre para armazenamento em cache, a fim de acelerar as leituras do disco. Mas quando a pressão real sobre a memória aumenta, três mecanismos entram em ação: swap, o OOM killer e os cgroups. Compreender como cada um deles se comporta e como configurá-los é a diferença entre um servidor que se degrada gradualmente sob carga e um que entra em falha sem aviso prévio.
Como o Linux gere as páginas de memória
Cada processo é executado no seu próprio espaço de endereços virtuais, até 128 TB em sistemas de 64 bits. O kernel mapeia estes endereços virtuais para a RAM física através de tabelas de páginas, com o Translation Lookaside Buffer (TLB) a armazenar em cache as pesquisas recentes. Um acerto no TLB demora cerca de 1 nanossegundo; um erro custa 20–100 nanossegundos, o que se acumula em cargas de trabalho que exigem muita memória, como bases de dados.
A memória física é dividida em páginas de 4 KB, e o kernel divide-as em duas categorias:
- Páginas apoiadas em ficheiros — ligadas a ficheiros no disco. O kernel pode descartar as páginas limpas ou esvaziar as sujas sem necessidade de swap.
- Páginas anónimas — memória de pilha e heap sem ficheiro de apoio. Estas têm de ser gravadas na área de troca antes de o kernel as poder libertar.
Em servidores com elevada procura de memória, uma grande proporção de páginas anónimas significa que o swap é envolvido precocemente. Observe o si (swap in) e so (swap out) em vmstat 1 — valores persistentes diferentes de zero são o seu primeiro aviso de que o sistema está sob pressão.
Para monitorização, use a ferramenta certa para a tarefa:
| Ferramenta | Ideal para | Métrica-chave |
|---|---|---|
free -h | Visão geral rápida de todo o sistema | available coluna |
vmstat 1 | Monitorização em tempo real de swap e E/S | si, so |
htop | Visualização interativa por processo | Barras de memória, lista de processos |
smem | Utilização precisa por processo | USS (Tamanho do Conjunto Único) |
/proc/meminfo | Detalhes ao nível do kernel | MemAvailable, Dirty, Slab |
Um erro comum: observar a free coluna free -h e entrar em pânico. A available coluna é o que importa. Ela inclui a memória que o kernel pode recuperar do cache quando necessário. Um servidor que mostra apenas 512 MB livres, mas 5 GB disponíveis, não está em apuros.
Quando a memória desce abaixo de um limiar, o kswapd demônio do kernel começa a recuperar páginas em segundo plano. Se isso não for suficiente, o kernel passa para a recuperação direta, bloqueando processos até que as páginas sejam libertadas. É daí que vêm os picos de latência. Defina um alerta quando MemAvailable cair abaixo de 10–15% da RAM total para que tenha tempo de reagir.
Configurar o swap
O swap é uma área do disco — seja uma partição ou um ficheiro — para onde o kernel move páginas anónimas inativas quando a RAM fica cheia. A diferença de velocidade é significativa: a RAM DDR4 tem uma latência de cerca de 100 ns, enquanto os SSDs NVMe têm cerca de 100 000 ns e os SSDs SATA aproximam-se dos 500 000 ns. O swap é um buffer de segurança, não RAM extra. Um servidor que depende constantemente do swap tem um problema de memória que mais swap não irá resolver.
Utilize um ficheiro de swap em vez de uma partição. É mais fácil de redimensionar e não requer reparticionamento.
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfileAdicione o ficheiro para /etc/fstab para que persista após reinicializações. A chmod 600 passo é obrigatório — quaisquer dados transferidos da RAM para o swap são legíveis a partir do swap, pelo que o ficheiro não deve ser legível por todos.
Após criar o swap, ajuste vm.swappiness. O valor padrão de 60 é agressivo. Para a maioria das cargas de trabalho de alojamento, é preferível que o kernel dê prioridade à RAM e só utilize o swap como último recurso:
| Função do servidor | vm.swappiness | vm.vfs_cache_pressure |
|---|---|---|
| Servidor web geral | 10–20 | 50 |
| Base de dados (MySQL/PostgreSQL) | 1–5 | 50 |
| Padrão (na maioria das distribuições) | 60 | 100 |
Para o dimensionamento da swap: 1–2 GB é suficiente para um VPS de 2 GB que lida com picos de tráfego ocasionais. Em sistemas com 8 GB ou mais, uma swap fixa de 2–4 GB é geralmente suficiente. O objetivo é dar ao kernel uma válvula de escape para páginas inativas, não para ampliar a memória endereçável total.
Em servidores com RAM limitada e CPU ampla, o zram cria uma área de swap comprimida na memória, evitando totalmente a E/S do disco. Vale a pena considerar em hosts VPS multi-tenant onde o NVMe é partilhado entre os tenants. Esteja atento à contenção de E/S se o swap residir no mesmo dispositivo que os ficheiros da base de dados — swap intenso e gravações de disco de alto débito não coexistem bem.
O OOM killer
Quando o kernel esgota a RAM e o swap e não consegue recuperar memória suficiente por outros meios, o OOM killer entra em ação. Ele pontua os processos utilizando a oom_badness() função:
points = (rss_anon + rss_file + rss_shmem + swapents + pgtables_pages) + (oom_score_adj × totalpages / 1000)O processo com a pontuação mais alta é encerrado. A fórmula favorece os grandes consumidores de memória, e o kernel evita encerrar vários processos em rápida sucessão, verificando se um processo já foi encerrado nos últimos 5 segundos.
Dois tipos de eventos OOM aparecem nos registos:
- OOM global — todo o sistema está sem RAM e swap. Os registos começam com
Out of memory: - Cgroup OOM — um contentor ou serviço atingiu o seu
memory.maxlimite. Os registos têm o prefixoMemory cgroup out of memory:
Para rever eventos OOM anteriores:
dmesg -T | grep -i "out of memory"
journalctl -k --grep="oom"Preste atenção ao order campo nos registos OOM. Um valor acima de 0 sugere fragmentação de memória em vez de esgotamento total — o kernel não conseguiu encontrar páginas contíguas suficientes, mesmo com memória livre disponível.
Pode influenciar quais os processos que o OOM killer alveja ajustando /proc/<pid>/oom_score_adj. O intervalo vai de -1000 (nunca encerrar) a +1000 (encerrar primeiro). Para serviços geridos pelo systemd, defina isto permanentemente no ficheiro de unidade:
[Service]
OOMScoreAdjust=-1000Parâmetros sysctl adicionais para ajustar o comportamento do OOM:
| Parâmetro | Valor | Efeito |
|---|---|---|
vm.overcommit_memory | 0 | Modo heurístico de overcommit padrão |
vm.overcommit_memory | 2 | Modo estrito; impede alocações que excedam RAM × overcommit_ratio + swap |
vm.panic_on_oom | 1 | Reinicia em vez de encerrar um processo |
vm.oom_kill_allocating_task | 1 | Encerra o processo que desencadeou o OOM em vez do maior consumidor |
Para monitorização proativa, verifique /proc/pressure/memory (Informações de Estagnação de Pressão, disponível desde o kernel 4.20). Observe o some avg10 valor: abaixo de 5% é normal; se se mantiver acima de 20%, significa que é provável que ocorra um evento OOM. Um allocstall contador em /proc/vmstat é outro sinal precoce — ele conta os bloqueios de recuperação direta, que muitas vezes precedem as interrupções por OOM. Ferramentas como systemd-oomd ou earlyoom podem agir com base nos limiares do PSI antes de o OOM killer do kernel ser acionado.
Cgroups e limites de memória
Os grupos de controlo (cgroups) permitem organizar processos em grupos e impor limites rígidos de recursos. Introduzidos no Linux 2.6.24, são a base dos ambientes de execução de contentores, incluindo Docker, Podman, Kubernetes e LXC. O kernel monitoriza a utilização de memória por cgroup, abrangendo memória anónima, páginas suportadas por ficheiros e objetos do kernel. Se um cgroup atingir o seu limite, o kernel recupera memória dentro desse grupo ou aciona um OOM kill no âmbito do cgroup.
O Cgroup v1 e o v2 diferem principalmente na forma como estão estruturados. O v1 monta cada controlador (memória, CPU, E/S) separadamente sob /sys/fs/cgroup/<controller>/, o que leva a um acompanhamento inconsistente dos recursos. A v2 utiliza uma hierarquia unificada em /sys/fs/cgroup/. O Kubernetes mudou para a v2 como padrão na versão 1.25 e deixou de suportar a v1 na 1.31.
Para verificar qual a versão que o seu sistema utiliza:
stat -fc %T /sys/fs/cgroup/cgroup2fs significa v2; tmpfs normalmente significa v1.
| Recurso | Cgroup v1 | Cgroup v2 |
|---|---|---|
| Hierarquia | Múltipla, por controlador | Única, unificada |
| Limite rígido de memória | memory.limit_in_bytes | memory.max |
| Limite de memória flexível | memory.soft_limit_in_bytes | memory.high (limitações) |
| Acompanhamento da utilização | memory.usage_in_bytes | memory.current |
| Métricas de pressão | Limitado | PSI integrado |
Os principais controlos de memória no cgroup v2:
| Parâmetro | Tipo | Descrição |
|---|---|---|
memory.max | Limite rígido | Exceder este valor aciona o OOM killer |
memory.high | Limite flexível | Limita a alocação e aciona a recuperação antes de atingir o limite rígido |
memory.low | Proteção flexível | A memória abaixo deste limiar é recuperada em último lugar |
memory.min | Proteção rígida | A memória abaixo deste nível nunca é recuperada |
memory.swap.max | Limite de swap | Defina como 0 para desativar a troca para este cgroup |
memory.oom.group | Booleano | Se ativado, o OOM encerra todos os processos no cgroup em conjunto |
Uma regra prática: defina memory.high cerca de 10–20% abaixo memory.max para dar ao kernel espaço para recuperar antes de atingir o limite rígido. Ao dimensionar memory.max, acrescente 20–30% acima do pico de utilização da aplicação para ter em conta a cache de páginas, que conta para o total de memória do cgroup.
Gerencie cgroups via systemd em vez de gravar diretamente no sistema de arquivos do cgroup. Use diretivas de arquivo de unidade como MemoryMax=, MemoryHigh=, e MemoryMin= para limites persistentes. Para testes rápidos:
systemd-run --scope -p MemoryMax=512M <command>Para pools de trabalhadores de servidores web, definir memory.oom.group=1 garante um encerramento limpo se um trabalhador exceder o seu limite — sem processos órfãos deixados para trás. Para motores de base de dados, memory.min protege o conjunto de buffers de ser recuperado sob pressão a nível do sistema.
Configuração de memória por função do servidor
As definições de memória corretas dependem da função do servidor. Aplicar a mesma configuração a uma base de dados e a um servidor web PHP prejudicará um deles.
| Função do servidor | vm.swappiness | Estratégia OOM | Política de Cgroup |
|---|---|---|---|
| Base de dados | 1–5 | Proteger (OOMScoreAdjust=-900) | Utilizar memory.min para proteger o buffer pool |
| Servidor Web/aplicações | 10–20 | Padrão | Limite por pool de trabalhadores via memory.max |
| Trabalhador em segundo plano | 60 | Eliminável (OOMScoreAdjust=+200) | Limitação via memory.high |
| VPS multi-tenant | 60 (com zram) | Padrão | Isolamento rígido por inquilino via memory.max |
Para MySQL e PostgreSQL, aloque 50–70% da RAM disponível para innodb_buffer_pool_size, desative as Transparent Huge Pages para reduzir picos de latência e proteja o processo com OOMScoreAdjust=-900 no ficheiro de unidade do systemd.
Para o PHP-FPM, dimensione os conjuntos de trabalhadores de acordo com a utilização real de memória. Cada trabalhador utiliza normalmente 30–100 MB. Divida a RAM alocada pelo tamanho médio dos trabalhadores para obter um pm.max_children . Use memory.max nos cgroups para limitar o pool.
Para cargas de trabalho com grande volume de gravações, defina vm.dirty_ratio para cerca de 10% e vm.dirty_background_ratio para 3%. Isto limpa as páginas sujas com maior frequência, evitando grandes bloqueios de E/S.
Torne o ajuste do kernel persistente guardando os parâmetros em /etc/sysctl.d/90-memory.conf. As configurações aplicadas em tempo de execução são perdidas ao reiniciar o sistema.
Para um resumo dos valores recomendados por função:
| Parâmetro | Servidor Web/aplicações | Servidor de base de dados |
|---|---|---|
vm.swappiness | 10–20 | 1–5 |
vm.vfs_cache_pressure | 50 | 50 |
vm.dirty_ratio | 15% | 10% |
vm.min_free_kbytes | 65536 | 65536 |
| Proteção OOM | Padrão | OOMScoreAdjust=-1000 |
Se estiver a executar cargas de trabalho de alta densidade e precisar de um servidor com capacidade suficiente para aplicar estas políticas corretamente, vale a pena dar uma vista de olhos aos servidores dedicados da FDC.

Gestão de memória do Linux: Swap, OOM Killer & Cgroups
Como o Linux swap, o OOM killer e o cgroups funcionam em conjunto - com exemplos de configuração para bases de dados, servidores Web e hosts VPS multi-tenant.
12 min de leitura - 31 de maio de 2026
Guia de configuração do Prometheus e do node_exporter
15 min de leitura - 29 de maio de 2026