03 - Systemd (Padrão Moderno)
video: https://youtu.be/... no frontmatter da nota.1. Ontologia e a Ruptura Arquitetural
A adoção do systemd representou a maior fratura ideológica e técnica na história do design do Linux. Enquanto o modelo clássico (SysVinit) aderia dogmaticamente à Filosofia Unix tradicional — compondo o sistema através de dezenas de pequenos binários isolados e scripts shell interpretados sequencialmente —, o systemd foi desenhado como um bloco monolítico e firmemente acoplado de bibliotecas C.
Sua premissa fundamental é que a inicialização e a orquestração do sistema operacional não são tarefas para interpretadores de texto baseados em bash. Lidar com o estado de processos, concorrência, timeouts, sinais de interrupção e coleta de descritores de arquivos (file descriptors) exige uma camada de gerenciamento de baixo nível, compilada, e com profundo conhecimento das estruturas do kernel (especificamente Control Groups e namespaces). O systemd não é apenas um "Init System"; ele é uma suíte de blocos de construção que padroniza o comportamento do sistema operacional, desde o milissegundo em que o núcleo entrega o controle em Ring 3 até o desligamento físico da ACPI.
2. Paralelismo Agressivo: A Topologia de Grafo (DAG)
O objetivo de engenharia primordial por trás da criação do systemd (liderado por Lennart Poettering) foi minimizar o tempo de inicialização (boot time) maximizando a utilização de processadores multicore. Para alcançar isso, o systemd aboliu o sequenciamento lexicográfico numérico.
Durante a inicialização, o PID 1 lê todas as configurações declarativas (Unit Files) simultaneamente e reconstrói o estado desejado do sistema como um Grafo Acíclico Dirigido (Directed Acyclic Graph - DAG) em memória. As relações entre unidades não são apenas "execute depois de"; elas possuem granularidade semântica complexa (Requires=, Wants=, BindsTo=, Conflicts=).
Uma vez que o DAG é computado, o systemd varre a base do grafo e executa absolutamente todos os processos que não possuem dependências bloqueantes de forma estritamente paralela. Se o serviço B requer o serviço A, B é enfileirado (job queue). O systemd possui lógicas internas para detecção de impasses (deadlock breaking): se um ciclo de dependência for detectado (A precisa de B, que precisa de C, que precisa de A), o orquestrador quebra o ciclo descartando a dependência mais fraca (Wants) para garantir que o boot não paralise eternamente.
3. O Paradoxo da Ordem: Ativação por Socket (Socket Activation)
Como paralelizar a inicialização de dezenas de serviços de rede que dependem uns dos outros? Se o servidor web (Nginx) precisa conectar-se ao banco de dados (PostgreSQL) e ao subsistema de logs (Syslog), a lógica tradicional dita que o Nginx deve esperar a inicialização completa de ambos. O systemd resolve isso importando e aperfeiçoando o conceito de Socket Activation do launchd (macOS).
A genialidade arquitetural reside na separação entre o socket de comunicação e o daemon provedor:
- No milissegundo 1 do boot, o próprio processo
systemd(PID 1) emite chamadas de sistemasocket(),bind()elisten()para todas as portas de rede locais e sockets UNIX IPC (Inter-Process Communication) necessários, como a porta 5432 do PostgreSQL e a porta 80 do Nginx. - O
systemdinicia todos os daemons (Nginx e PostgreSQL) simultaneamente. - Quando o processo do Nginx acorda, ele imediatamente tenta se conectar ao PostgreSQL na porta 5432. O daemon do PostgreSQL ainda está alocando memória e lendo o disco, mas o socket já existe no kernel.
- O kernel Linux aceita o pacote TCP SYN do Nginx e o coloca no buffer de escuta do socket. O Nginx fica bloqueado em estado de espera síncrona na chamada
connect(), mas não falha nem sofre de recusa de conexão (Connection Refused). - Quando o processo do PostgreSQL finalmente termina sua inicialização, o
systemdpassa o descritor de arquivo (File Descriptor) do socket da porta 5432 para ele viaexec(). O banco de dados consome a fila do buffer e responde ao Nginx.
A Ativação por Socket torna a ordem de inicialização irrelevante. Todos os daemons podem ser disparados simultaneamente, com o kernel atuando como um amortecedor de sincronia. Além do boot, isso permite o Lazy Loading (carregamento sob demanda): o systemd pode manter um socket SSH aberto e só forkar o binário sshd quando o primeiro pacote chegar pela rede, economizando RAM em instâncias ociosas.
4. Rastreamento Determinístico de Estado: Integração com Cgroups
O calcanhar de Aquiles do modelo SVR4 era a técnica de double-forking. Quando um daemon se colocava em background, o PID 1 perdia sua linhagem de execução, dependendo de frágeis arquivos /var/run/*.pid que podiam sofrer de PID recycling ou corrupção.
O systemd resolveu o rastreamento de estado de forma inatacável integrando-se nativamente ao subsistema de Control Groups (cgroups) do kernel Linux.
Quando o systemd decide iniciar um serviço (ex: apache2.service), ele não chama simplesmente um fork. A mecânica é muito mais profunda:
- O PID 1 invoca a API do kernel para criar um novo e exclusivo diretório
cgroupna hierarquia do sistema de arquivos virtual/sys/fs/cgroup/systemd/system.slice/apache2.service/. - O PID 1 realiza o fork, escreve o PID do novo processo filho dentro do arquivo
cgroup.procsdaquele subdiretório e, só então, executa o binário do Apache viaexecve(). - A partir deste momento, as regras do kernel aplicam-se: não importa se o processo pai do Apache faz mil forks, cria subprocessos workers e morre. Todo e qualquer processo derivado herdará obrigatoriamente a assinatura daquele
cgroup. Nenhum processo pode escapar de um cgroup (sem privilégios explícitos).
Isso confere ao systemd poderes absolutos sobre a máquina de estados. Quando o administrador executa systemctl stop apache2, o systemd não lê arquivos PID. Ele simplesmente envia um sinal SIGTERM para o cgroup inteiro, e o kernel se encarrega de irradiar o sinal de terminação para cada thread subjacente associada àquele serviço. Serviços "renegados" (rogue processes) ou zumbis isolados tornam-se arquiteturalmente impossíveis.
Além de morte determinística, o acoplamento aos cgroups permite o controle granular de recursos nativo (Resource Control). Diretamente no arquivo .service, o administrador pode definir MemoryLimit=500M ou CPUQuota=20%, e o PID 1 aplicará essas restrições ao instanciar o serviço, absorvendo o que antigamente era função de bibliotecas complexas como cgmanager ou ulimit.
5. Eventos Assíncronos e a Eliminação do "Polling"
A arquitetura moderna deve reagir dinamicamente às mutações do hardware. O systemd unifica o espaço do usuário respondendo a eventos originados no barramento de dispositivos e no subsistema de rede.
Através de uma simbiose com o udev (que agora faz parte da árvore de código-fonte do systemd), os eventos gerados pelo kernel (como plugar um cabo de rede ou inserir um disco iSCSI) são propagados instantaneamente. O systemd suporta Ativação por Dispositivo (Device Activation). Uma unidade de serviço pode conter a diretiva BindsTo=dev-sdb1.device. Se o disco /dev/sdb1 for desconectado fisicamente, o udev notifica o PID 1, que imediatamente e automaticamente derruba os serviços de banco de dados que dependiam daquele volume de bloco para funcionar, prevenindo a corrupção do journal da aplicação.
6. O D-Bus como Espinha Dorsal de Comunicação (IPC)
Em ecossistemas legados, os utilitários se comunicavam lendo a saída de texto (stdout) uns dos outros ou lendo arquivos em /etc. A quebra de estabilidade era constante se o formato da string de resposta mudasse.
No ecossistema do systemd, o estado do gerenciador de inicialização e as propriedades de toda e qualquer unidade são mantidos e expostos através de uma API tipificada orientada a objetos transmitida pelo D-Bus (um sistema de Inter-Process Communication de alta performance). Ferramentas como o comando systemctl não executam o desligamento de um processo por conta própria. Eles atuam meramente como clientes IPC. Ao digitar systemctl restart nginx, o utilitário converte o comando em uma requisição D-Bus (ex: org.freedesktop.systemd1.Manager.RestartUnit) e a envia ao PID 1.
Isso desassociou o frontend do backend. O PID 1 atua como o servidor absoluto de estado, permitindo que bibliotecas em Python, C, Go, ou painéis administrativos interativos (Cockpit) consultem atributos com precisão binária, eliminando a era da engenharia frágil baseada no parsing de ferramentas de linha de comando.