02 - Estrutura e Conteúdo (cpio, gzip)
video: https://youtu.be/... no frontmatter da nota.A transição arquitetural do obsoleto initrd para o moderno initramfs exigiu uma mudança fundamental na forma como os dados de inicialização são empacotados e processados pelo kernel Linux. Enquanto o initrd era uma imagem de disco geométrica e formatada (geralmente ext2), o initramfs é, em sua essência, um arquivo compactado que contém uma hierarquia de arquivos e diretórios a ser extraída sequencialmente para a memória RAM. Para entender a eficiência e a flexibilidade deste modelo, é imperativo dissecar o formato de arquivamento escolhido, os algoritmos de compressão suportados e a anatomia exata do conteúdo que habita este ambiente efêmero.
1. O Formato CPIO (Copy-In, Copy-Out)
O formato padrão absoluto para o empacotamento do initramfs não é o tar (Tape Archive), onipresente no espaço de usuário, mas sim o cpio. Historicamente derivado do Unix System III e padronizado pelo POSIX.1, o cpio foi selecionado para o kernel Linux devido a vantagens arquiteturais cruciais no momento de extração crua (Ring 0).
1.1. Por que CPIO e não TAR?
Embora o tar seja mais popular, seu formato de cabeçalho exige preenchimento (padding) em blocos de 512 bytes e não foi originalmente desenhado para representar nós de dispositivos especiais (como blocos e caracteres) de forma padronizada entre diferentes arquiteturas Unix.
O cpio, especificamente o formato **SVR4 newc** (código mágico hexadecimal 070701), foi aprimorado para suportar sistemas de arquivos modernos com identificadores de inode de 32 bits (e mais tarde de 64 bits), propriedades de dispositivos (major/minor numbers) e hard links robustos.
A maior vantagem do cpio para o kernel é sua natureza estritamente contínua (streamable). O kernel pode alocar um fluxo de leitura a partir do endereço de memória onde o bootloader despejou o arquivo e processar metadados e conteúdos em uma única passagem (leitura sequencial $O(n)$), sem jamais precisar de operações de seek (busca aleatória para frente ou para trás).
1.2. O Desempacotador Interno do Kernel
Durante a rotina de inicialização, a função C populate_rootfs() (presente em init/initramfs.c no código-fonte do kernel) assume o controle. Ela não "monta" o cpio; ela literalmente lê o cabeçalho de cada arquivo e executa as syscalls sys_mkdir, sys_mknod, sys_symlink e sys_write para instanciar instantaneamente os inodes nas estruturas VFS do rootfs (um tmpfs alocado dinamicamente na RAM).
2. Compressão de Dados: Do gzip aos Algoritmos Modernos
Um cpio descompactado contendo binários, bibliotecas genéricas (como a glibc) e módulos de kernel pode facilmente ultrapassar 100 MB. Como esse arquivo precisa ser transferido do disco para a RAM pelo bootloader (um processo frequentemente lento em hardwares antigos) e ocupa memória valiosa irrecuperável até a execução do switch_root, a compressão é mandatória.
2.1. O Padrão gzip
O padrão histórico para a compressão do initramfs é o algoritmo Deflate, encapsulado no formato gzip (.cpio.gz). O código de descompressão do zlib é pequeno o suficiente para ser embutido com baixo impacto no kernel monolítico, oferecendo um excelente equilíbrio entre taxa de compressão e velocidade de extração. O magic number do gzip (0x1F 0x8B) é varrido nativamente pela rotina de extração.
2.2. A Evolução: lz4, xz e zstd
Com o aumento do tamanho das imagens (devido ao firmware de GPUs e módulos estendidos de rede), novos algoritmos foram integrados ao kernel:
- XZ / LZMA: Oferece compressão máxima. Ideal para sistemas embarcados onde o armazenamento (Flash/EEPROM) é escasso, mas penaliza severamente o tempo de CPU (aumentando o tempo de boot).
- LZ4: O extremo oposto do XZ. O
lz4possui uma taxa de compressão inferior aogzip, mas sua velocidade de descompressão é vertiginosa, operando quase à velocidade limite da RAM. Em servidores modernos, substituirgzipporlz4noinitramfspode cortar segundos do tempo de boot. - Zstandard (zstd): A solução definitiva atual. Desenvolvido no Facebook, o
zstdoferece taxas de compressão comparáveis aoxz, com velocidades de descompressão próximas aolz4. A maioria das distribuições modernas (Fedora, Arch, Ubuntu) migrou a geração doinitramfsparazstdpor padrão.
O kernel tenta identificar a assinatura de compressão lendo os primeiros bytes da imagem. Se a compilação do kernel possuir o módulo descompactador apropriado (ex: CONFIG_RD_ZSTD=y), ele transparentemente envia o fluxo comprimido para a biblioteca de descompressão antes de passar pelo parser do cpio.
3. Anatomia e Hierarquia Interna
Se você interromper a inicialização de um sistema ou descompactar manualmente a imagem do initramfs (via zcat initramfs.img | cpio -id), revelará uma estrutura de diretórios minimalista que mimetiza o FHS (Filesystem Hierarchy Standard), mas puramente focada na sobrevivência transitória.
3.1. O Binário Central: /init
O coração absoluto do arquivo é o executável localizado na raiz e nomeado estritamente como /init. O kernel, após extrair o arquivo cpio, tenta invocar este binário em espaço de usuário, outorgando-lhe o PID 1. Se este arquivo não existir (ou falhar devido a dependências compartilhadas ausentes, como a libc), o kernel invoca uma chamada de Panic (kernel panic - not syncing: No working init found). Este binário não é o systemd completo da máquina, mas frequentemente uma versão podada do mesmo, ou um shell script sequencial espesso.
3.2. A Estrutura de Diretórios Crítica
A árvore gerada tipicamente contém:
/bin,/sbin,/usr/bin: Contêm um conjunto mínimo de ferramentas. Para economizar espaço, em vez de incluir centenas de binários (comols,mkdir,mount,modprobe,sh), ferramentas geradoras frequentemente incorporam o BusyBox. O BusyBox é um único executável estático que combina o funcionamento das utilidades core do UNIX; os comandos são apenas symlinks apontando para o/bin/busybox. Em implementações baseadas emsystemd(via Dracut), as versões reais dos binários podem ser utilizadas, dependendo das configurações./lib,/lib64: Bibliotecas compartilhadas estritamente necessárias para a execução dos binários de/bin. A ferramentalddé usada indiretamente durante a criação doinitramfspara puxar os arquivos.soexatos requeridos./lib/modules/$(uname -r)/: O núcleo do propósito doinitramfs. Não contém todos os drivers do sistema, apenas o subconjunto selecionado na criação (controladoras SATA/AHCI, NVMe, USB, teclados, drivers de criptografia dm-crypt)./etc: Configurações mínimas. Geralmente umfstabreduzido, configurações do LVM (lvm.conf), módulos que devem ser forçados a carregar (/etc/modules-load.d/), ou chaves SSH se oinitramfsfor configurado para aceitar desbloqueio remoto de partições via rede (usando dropbear)./dev,/proc,/sys,/run: Diretórios vazios (pontos de montagem) que o/initpovoará imediatamente antes de procurar o disco rígido raiz.
4. O CPIO Não Comprimido (Early Microcode)
Uma anomalia arquitetural vital introduzida em tempos recentes é o conceito de arquivos concatenados (Early Initramfs). Processadores x86 modernos (Intel e AMD) necessitam de atualizações de microcódigo (correções de falhas de silício, como Spectre e Meltdown). Essas correções precisam ser aplicadas à CPU nos primeiros milissegundos de operação do kernel, muito antes das rotinas de descompressão de memória (zlib, zstd) serem instanciadas pela MMU e pelos algoritmos de gerenciamento de memória inicial do Ring 0.
Como aplicar o microcódigo se o initramfs está comprimido?
A solução da arquitetura do Linux explora uma peculiaridade do utilitário cpio: o kernel suporta múltiplos arquivos cpio concatenados sequencialmente em um único binário (initramfs.img).
Estruturalmente, um initramfs moderno é composto por:
- Um pequeno arquivo CPIO em formato RAW (não comprimido) contendo exclusivamente arquivos sob o diretório
/kernel/x86/microcode/. Como não está comprimido, o subsistema de boot inicial do kernel x86 pode varrer os bytes na memória física e aplicar a correção de CPU imediatamente. - Seguido, no mesmo arquivo, pelo CPIO principal comprimido (
gzipouzstd), contendo a estrutura de pastas/bin,/lib, e o/init.
O kernel lê o fluxo de memória; quando encontra o final do primeiro arquivo cpio (sinalizado pelo registro mágico TRAILER!!!), ele verifica se os próximos bytes correspondem a uma assinatura de compressão e redireciona o fluxo restante para o descompressor dinâmico, criando um sistema empacotado bifásico de altíssima eficiência.