Home Comunidade Eventos YouTube Networks Desafios // produtos Academy News CTI | CVE Contato

03 - Systemd (Padrão Moderno)

video explicativo
Video explicativoEspaco reservado para o video desta anotação — adicione 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:

  1. No milissegundo 1 do boot, o próprio processo systemd (PID 1) emite chamadas de sistema socket(), bind() e listen() 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.
  2. O systemd inicia todos os daemons (Nginx e PostgreSQL) simultaneamente.
  3. 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.
  4. 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).
  5. Quando o processo do PostgreSQL finalmente termina sua inicialização, o systemd passa o descritor de arquivo (File Descriptor) do socket da porta 5432 para ele via exec(). 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:

  1. O PID 1 invoca a API do kernel para criar um novo e exclusivo diretório cgroup na hierarquia do sistema de arquivos virtual /sys/fs/cgroup/systemd/system.slice/apache2.service/.
  2. O PID 1 realiza o fork, escreve o PID do novo processo filho dentro do arquivo cgroup.procs daquele subdiretório e, só então, executa o binário do Apache via execve().
  3. 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.