Memória virtual
Cada processo acha que tem toda a memória para si — mas o SO mapeia endereços virtuais para endereços físicos via page table. Isso permite isolamento, compartilhamento e mais memória do que a RAM física disponível.
O endereço que você vê é uma ilusão
Quando você escreve int* p = malloc(4);, o compilador gera código que acessa
endereços virtuais — não endereços físicos de RAM. A CPU traduz cada endereço
virtual para físico em tempo de execução, usando uma estrutura chamada page table.
A memória é dividida em páginas (tipicamente 4 KB). A page table mapeia páginas virtuais para frames físicos. Se uma página virtual não está em RAM (não está mapeada), a CPU gera um page fault — o kernel é chamado, carrega a página do disco, atualiza a page table, e o processo continua como se nada tivesse acontecido.
libc.so é mapeada para
múltiplos processos compartilhando os mesmos frames físicos (somente leitura).
Simulador de tradução de endereços
Clique em qualquer página virtual para simular o acesso. O sistema mostra se foi TLB hit (rápido), TLB miss com page table lookup, ou page fault com carregamento da página e substituição LRU.
Clique em uma página virtual para simular o acesso. O sistema mostrará se foi TLB hit, TLB miss ou page fault — e como o kernel resolve cada caso.
Paginação em 4 níveis (x86-64)
// Tradução de endereço virtual → físico (x86-64, 4KB páginas) // Endereço virtual de 48 bits: // bits[47:39] = índice no PML4 (512 entradas) // bits[38:30] = índice no PDPT (512 entradas) // bits[29:21] = índice no PD (512 entradas) // bits[20:12] = índice no PT (512 entradas) // bits[11:0] = offset na página (0–4095) // Tradução de 0x7fff12345678: const vaddr = 0x7fff12345678n; const pml4_idx = (vaddr >> 39n) & 0x1FFn; // → 0xFF const pdpt_idx = (vaddr >> 30n) & 0x1FFn; // → 0x1FC const pd_idx = (vaddr >> 21n) & 0x1FFn; // → 0x091 const pt_idx = (vaddr >> 12n) & 0x1FFn; // → 0x145 const offset = vaddr & 0xFFFn; // → 0x678 // Sem TLB: 4 acessos à RAM (PML4→PDPT→PD→PT) + 1 acesso ao dado = 5 acessos // Com TLB hit: PTE em cache → apenas 1 acesso ao dado // Por isso o TLB é crucial: 99%+ de hit rate em workloads típicos
Algoritmos de substituição de páginas
// Algoritmos de substituição de páginas // Sequência de acesso: 7 0 1 2 0 3 0 4 2 3 0 3 2 // 3 frames de RAM disponíveis // FIFO (First In, First Out): // Substitui a página mais antiga. Simples mas ineficaz. // Paradoxo de Bélády: mais frames → mais page faults com FIFO! // 9 page faults para a sequência acima. // LRU (Least Recently Used): // Substitui a página usada menos recentemente. // Usa pilha de páginas ou contador de acesso. // 8 page faults — melhor que FIFO, mas overhead de rastreamento. // OPT (Ótimo — só teórico): // Substitui a página que será usada mais tarde no futuro. // 6 page faults — limite inferior, impossível na prática. // Linux usa uma aproximação LRU com 2 listas: // active list (quente) e inactive list (fria). // O bit "accessed" da PTE é limpo periodicamente; // se a página não foi acessada → move para inactive → candidata a swap.
Explorando memória virtual
Mini projeto: em C, leia /proc/self/maps e imprima todas as VMAs (Virtual Memory Areas) do seu próprio processo: endereço de início/fim, permissões, nome do arquivo mapeado. Identifique: stack, heap, código do programa, libc.so, vDSO.
Projeto principal: implemente o algoritmo de substituição de páginas LRU em Python: classe PageCache(capacity) com método access(page) que retorna True se page fault e False se hit. Use uma deque para rastrear ordem de uso. Teste com a sequência do código acima e valide o número de page faults.
Desafio extra: use mmap() + madvise(MADV_SEQUENTIAL) para mapear um arquivo grande e processar sequencialmente. Compare com madvise(MADV_RANDOM). Monitore page faults com perf stat -e page-faults ./prog. Observe como a dica de acesso muda o número de page faults e a velocidade.
Teste sua intuição
Onde você encontra isso
Swap e zRAM
Linux swap armazena páginas em disco quando a RAM está cheia. Android e dispositivos embarcados usam zRAM: uma partição de swap comprimida na própria RAM. zRAM comprime páginas frias com LZ4 ou zstd, efetivamente aumentando a capacidade útil da RAM em 2–3×. Um Android com 4GB de RAM + zRAM comporta mais apps abertos.
ASLR (Address Space Layout Randomization)
ASLR randomiza os endereços base da stack, heap e bibliotecas a cada execução. Um exploit que hardcode o endereço de system() em libc falha porque o endereço virtual muda. O SO gera o offset aleatório no mmap — a page table mapeia o mesmo código físico para endereços virtuais diferentes em cada processo.
Huge pages e TLB pressure
Com 4KB de páginas e 16GB de RAM, a page table pode ter 4 milhões de entradas. O TLB cobre apenas ~1500 entradas — com acesso aleatório, muitos TLB misses. Huge pages (2MB ou 1GB) reduzem o número de entradas de page table e TLB pressure: bancos de dados (PostgreSQL, Oracle) e aplicações HPC habilitam huge pages explicitamente para ganhos de 5–30%.