 |
Linux: MAIS DO QUE UM UNIX |
No artigo
"O que define um Unix?" mostrei que Linux é um legitimo Unix, mas uma coisa que muita gente não sabe é que Linux se tornou mais do que um Unix
possuindo sua própria API. Quando
analisei o ext4 do HelenOS para descobrir se tratava-se do próprio filesystem do Linux ou feito do zero, uma das coisas que eu fiz foi exatamente tentar identificar em seu código algo específico do Linux. Para se ter uma ideia do que estou falando, reparem as linhas
#include dos arquivos
balloc de ambos os Ext4:
 |
Arquivo balloc.c do Ext4 do Linux |
 |
Arquivo balloc.c do Ext4 do HelenOS |
Interessante MAS... para que possuir uma API própria se Linux já é um sistema operacional Unix? Ou seja, ele possui suporte as especificações
POSIX e
SUS assim como todos outros Unix. Para responder a essa pergunta é interessante ler a respeito dos mitos sobre o systemd que Lennart publicou em seu blog. E é aí que chegamos no
mito de número 16:
 |
16. Mito: systemd não é portável por razão nenhuma.
Sem sentido! Utilizamos funcionalidade específica do Linux porque precisávamos dela para implementar o que queríamos. Linux possui tantos recursos que UNIX/POSIX não possuíam, e queríamos capacitar os usuários com esses recursos. Esses recursos são incrivelmente uteis, mas somente se eles são expostos de verdade de um jeito amigável ao usuários, e é isso o que fazemos com o systemd.
|
FOSDEM: Qual funcionalidade específica do Linux que o systemd utiliza e qual a vantagem dessa sobre uma solução que é portável para outros sistemas operacionais?
Lennart Poettering: Há um monte de funcionalidades específicas do Linux que confiamos. A primeira que vem a mente provavelmente é o cgroups (abreviação de Control Groups) que é um recurso do kernel Linux que pode ser usado para criar processos de grupos hierárquicos, criar label para esses e opcionalmente aplicar limites de recurso ou outras regras para tais. Mas há mais um monte. O systemd íntegra muito bem com o sistema udev que é específico do Linux para eventos hot-plug. Outra, a solução para disk read-ahead incluímos nos usos do systemd, a fanotify() call também específica do Linux. Ou adicionamos suporte a processos spawning em seus próprios namespaces ou com definições limitadas de capacidades, ambas nas quais são features específicas do Linux. Ou adicionamos suporte ao automouter específico do Linux e outras APIs mount tal como polling mount changes via /proc/self/mountinfo na qual não existe em outros sistemas operacionais. Internamente nós utilizamos um monte de API calls mais novas, como a timerfd() ou signalfd() que não estão disponíveis fora do Linux. Essa últimas calls puderam ser emuladas em outros sistemas operacionais, mas utilizá-las simplifica muito o nosso próprio código. E muitos outros features do Linux que utilizamos não possuem contrapartidas adequadas em outros Unixes.
Não ter que se importar com portabilidade tem duas grandes vantagens: podemos fazer máximo uso do que o kernel Linux moderno oferece nesses dias sem dores de cabeça -- Linux é um dos kernels mais poderosos existentes, mas muitos de seus features não tem sido utilizados pelas soluções anteriores. E segundo, ele simplifica muito bem nosso código e o torna menor: desde que nunca precisamos abstrair interfaces do sistema operacional, o montante de Código grudado (glue code) é mínimo, e consequentemente o que ganhamos é uma chance bem menor de gerar bugs, uma chance bem menor de confundir o leitor do código (consequentemente melhor manutenção) e uma footprint bem menor.
Muitos dos meus projetos anteriores (incluindo PulseAudio e Avahi) foram escritos para serem portáveis. Sendo aliviados das correntes que a exigência por portabilidade coloca em você é um tanto libertador. Enquanto que garantir portabilidade quando se trabalha em aplicações de alto nível não é necessariamente um trabalho difícil, se torna crescentemente mais difícil se a coisa na qual você trabalha é um componente do sistema (os quais o systemd, o PulseAudio e o Avahi são).
De fato, o jeito que eu vejo as coisas na API do Linux anda tomando o papel da API POSIX e o Linux é o ponto focal de todo o desenvolvimento de software livre. Devido a isso eu só posso recomendar aos desenvolvedores que tentam hackear somente com Linux em mente e experimentar a liberdade e as oportunidades que ele lhe oferece. Então, obtenha uma cópia do "The Linux Programming Interface", ignore tudo o que ele diz sobre compatibilidade POSIX e parta para a hack em seu surpreendente software Linux. É bastante aliviante!
FOSDEM: Qual é o ponto chave do systemd?
Lennart Poettering: Não há apenas um, há vários. Já que eu não consigo listar, eu vou mencionar um único. Um que provavelmente surpreende muitos leitores: systemd é o primeiro init system do Linux que lhe permite matar um serviço corretamente. Surpreso com essa declaração? Mas é verdade. Matar uma daemon no Linux é realmente difícil e sem systemd é na verdade quase impossível fazer isso corretamente. (Não, um simples "killall httpd" é devido a muitas razões inadequadas de matar o Apache). Se você quiser saber porque, eu digo o que o systemd faz diferentemente aqui...
Agora que já temos algum ponto de referência, podemos trabalhar em nosso estudo sobre tais recursos. Vou abordar mesmo os já mencionados por Lennart. Lembrando que se trata de pontos da parte de desenvolvimento, mas também irei tratar sobre tais recursos de acordo com a visão de um sysadmin e de usuários comuns (já que também é a razão pelas quais esses recursos existem).
Já mencionado anteriormente, esse recurso foi inicialmente desenvolvido por engenheiros do Google com o nome de
Process Container.
E para evitar confusão com
container, seu nome foi alterado (vale
lembrar que quando falamos de container, não estamos tratando unicamente
de
Docker.
O Red Hat Enterprise Linux 8 adota diferentes soluções de containers).
No vídeo
A Tragédia do systemd,
Benno Rice (desenvolvedor do
FreeBSD) menciona que a comunidade
FreeBSD tem como argumento
"mas nós temos o Jails no FreeBSD". Benno responde: "Sim tem, mas o Cgroups é muito mais granular, muito mais flexível." Além do systemd, o cgroups é utilizado por projetos como o Docker, o Firejail, o LXC e lmctfy.
É uma ferramenta para carregar aplicações e daemons sob demanda (somente quando os serviços são necessários), simplificar a forma como as aplicações se comunicam, ajudar a coordenar o ciclo de vida dos processos e tornar mais simples e mais confiável de codificar aplicações
single instance ou daemons. A lista de projetos que fazem uso do D-Bus é enorme (em torno de uns 210 projetos no momento em que escrevo sobre o D-Bus) e
podem ser conferidos clicando aqui.
Dado como a base fundamental dos containers,
namespace (
man 7 namespace) isola um recurso global do sistema em uma instancia tornando-o invisível a outros processos. Foi inspirado no
Name Space do Plan9 (como sempre, o Plan9 contribuindo bastante).
O Docker é a ferramenta mais famosa a utilizar o namespace (uma vez que o Docker faz na verdade, uso de ferramentas já existentes no Linux. E sim, Docker é especifico para Linux assim como o systemd).
 |
namespace no Docker. |
Netlink é o responsável por realizar a comunicação (transferência de informações ou troca de mensagens) entre o kernel space e o user space (kernel space e user space é inclusive uma parte essencial que eu tratei no meu artigo
5 diferentes modelos de kernel).
É composto por interface de sockets para processos do user space e uma API interna do kernel para os módulos do kernel. Também pode ser utilizado como IPC (InterProcess Communication) para permitir processos compartilharem dados entre si.
O Netlink é uma ferramenta fundamental para o funcionamento
Iproute2. tanto que em versões anteriores das distribuições como é o caso RHEL 6 (que tinham o
Net-tools como padrão), além de ser necessário instalar o Iproute2, era também necessário configurar e compilar um novo kernel já que não vinham com a maioria dos recursos de controle trafego por padrão.
A musl possui suporte a vários desses recursos (conferir a linha
Various Linux extensions. Linux extensions referem-se a kernel interfaces fornecidas pelo Linux fora do scope da POSIX e como o epoll, signalfd, extended attributes, capabilities, carregamento de módulo e assim por diante).
O autofs é uma
daemon utilizada para montagem automaticamente dos sistemas de arquivos (o que pode incluir sistemas de arquivos de rede, CD-ROMs, floppies e etc.) sob demanda através do
automount e desmontá-los depois de um tempo que não estiver utilizando. A intenção do autofs é economizar recurso computacional e melhorar o desempenho (tentando evitar o uso do /etc/fstab).
Abreviação de
Secure Computing, o Seccomp serve para tornar o acesso a uma
thread mais restrita à um numero pequeno de
syscalls. De forma mais simples de entender, podemos dizer que o Seccomp é uma
Sandbox. O Seccomp faz uso da system call
BPF (
Berkeley
Packet
Filters.
man 2 bpf) como uma espécie de filtro para os programas. Há também a
libsecomp que provê meios de facilitar o uso do Seccomp e do BPF.
Iniciado no kernel 2.2, Linux Capabilities servem para verificação de permissões. São
atributos especiais do kernel Linux que garantem privilégios administrativos específicos à processos e à binários que geralmente são reservados e destinados ao
ID 0 (ou seja, o usuário
root). O que o Capability faz é dividir os privilégios do usuário root em pequenas partes (em
unities) garantido assim ao processo privilégios específicos e não todo os privilégios que o usuário root possui (algo parecido com o SUDO ou com os bits especiais, só que de forma mais restrita). Há em torno de 40 capabilities implementadas até o kernel 5.10.
Surgiu no
kernel 2.6 como substituto o antigo
devfs oferecendo uma base mais limpa e mais robusta de gerenciamento dos diretórios no
/dev. O
sysfs também surgiu o kernel 2.6 que é gerenciado pelo kernel para exportar informações básicas sobre dispositivos conectados recentemente sendo montado no diretório /sys (o udev pode fazer uso de informações do sysfs para criar device nodes correspondentes ao hardware relacionado).
O
systemd-udev faz uso de instruções especificadas na regras do udev. Uma boa base de leitura sobre gerenciamento de dispositivos com o systemd-udev
é esta aqui.
Evdev
Como descrito em sua
manpage, o
evdev é um driver do
Xorg que cuida dos eventos de dispositivos de entrada em
/dev/input. Possui suporte a mouse, teclado, tablet e touch‐screen. Existem também a
libevdev e evdev para as linguagens
Go e
Python.
O
ALSA (
Advanced Linux Sound Architecture, traduzido para português do Brasil como Arquitetura Avançada de Som do Linux) é o servidor de áudio (e framework) responsável pela parte de áudio do Linux. O ALSA gerencia o acesso a placa de som (as interfaces de áudio) e permite que outros programas como esd, aRTs (descontinuado), JACK e o
PulseAudio façam acesso às interfaces.
Foi o substituto do antigo
OSS (
Open
Sound
System) da
4front Technologies (apesar que seu ultimo lançamento foi em 2019 para o kernel 4.15). Eu e um amigo debatemos o motivo desta transição em uma série chamada
Assunto games (bastando clicar aqui) e lá o Anderson explica as limitações que ocorriam no OSS.
DRM é um módulo do kernel que permite acesso direto ao hardware (algo parecido com o que acontece com sistema operacional
exokernel). Surgiu no kernel Linux 2.2.18, o DRM fornece vários serviços gráficos a drivers de vídeo (que incluem gerenciamento de memória, gerenciamento de saída, de framebuffer, serviços de DMA e muito mais) através da biblioteca
libdrm. O DRM também fornece gerenciamento a monitores através do
Kernel Mode-Setting (KMS).
O DRM é tão interessante que foi portado para o
DragonflyBSD como pode ser lido no texto abaixo:

A API epoll permite as aplicações monitorarem múltiplos descritores de arquivos para determinar quais descritores estão preparados para realizar entrada e saída de forma mais eficiente que as antigas syscalls
select() e
poll() que apresentavam ser pobres para as aplicações de redes modernas, ter pobre desempenho devido ao seu design e entregavam ao kernel uma lista completa com todos os descritores de arquivos (que a cada chamada, tinha que ficar reexaminando a mesma lista).
epoll Essa é uma das dependências do Wayland. O FreeBSD possui um recurso similar chamado
kqueue.
O NetBSD também possui possui patches para o kqueue no pkgsrc mas que na época que
anunciaram que planejavam portar o Wayland, essses patches não haviam sido aceito upstream.
O propósito do
timerfd é que, uma vez que uma API se torna disponível no user space, ela deve possuir suporte indefinidamente para todos os propósitos sem quebrar as aplicações. Já que há vezes que essas regras são quebradas, mesmo em áreas conhecidas para distúrbios como o sysfs, para isso foi criado o timerfd e assim manter maior integridade dos arquivos.
O timerfd permite que uma aplicação possa obter os descritores de um arquivo para utilizar com eventos e assim eliminar a necessidade de sinais (signals). Já o
signalfd é o responsável por criar descritores que podem ser utilizados para aceitar os sinais. Os sinais a que me refiro são por exemplo utilizados no comando
kill como podem ser conferidos na
manpage man 7 signal.
Linux Security Module (LSM) é um framework de segurança ao kernel. São na verdade extensões de segurança do kernel e não módulos que fornecem interface de politica de segurança
MAC (
Mandatory
Access
Control). Dentre eles temos o
SELinux (o mais famoso deles sendo utilizado por padrão pelo RHEL, o Fedora e o CentOS); o AppArmor utilizado por padrão no Debian, o LoadPin, o Smack, o TOMOYO, o Yama e o SafeSetID.
O Integrity Measurement Architecture (ou simplesmente IMA) serve como subsistema de integridade do kernel que detecta se arquivos foram alterados acidentalmente ou maliciosamente, sejam remotamente ou localmente. O IMA faz parte dos módulos LSM anteriormente mencionados.
Fanotify também conhecido como o
fscking e anteriormente conhecido anteriormente como
TALPA, tem como propósito principal servir de scanner de malware no Linux (viruses, root kits, spyware, ad-ware e etc...)
"Ué, mas Linux não tem vrius" (sabe de nada inocente). Surgiu na Red Hat em 2008 devido na época o kernel Linux não oferecer uma interface completamente adequada para implementar tais soluções de segurança. Esta ferramenta foi desenvolvida inclusive para atender as necessidades de muitas empresas que fornecem serviços de ati-malware.
CONCLUSÃO
A maioria dos apaixonados afirmam que Linux não é um Unix. E honestamente elas estão certas; Linux não é um Unix; Linux é mais do que um Unix. Linux não se limitou somente a o que todos os outros os Unix são ou tinham a oferecer. Linux resolveu explorar melhor o seu potencial.
Além de ser melhor do que muitos sistemas operacionais em várias áreas (SMP, desempenho, redes, virtualização e muitas outras áreas), ainda agregou recursos que o permitem abranger áreas que seriam inimagináveis a outros sistemas operacionais.
No
artigo "The Hurd and Linux" do site gnu.org é descrito que
Linux é arquiteturalmente igual ao kernel Unix e que o trabalho do projeto GNU se direciona a algo muito mais poderoso. O argumento apresentado por Richard Stallman baseia-se na proposta da arquitetura do microkernel
(caso não entenda o que é microkernel, sugiro a leitura do meu artigo sobre 5 modelos diferentes de kernel) e que até hoje não aconteceu. Treze anos depois do lançamento do Linux, foi escrito o
livro Open Life (traduzido pra inglês por
Sara Torvalds, a própria irmã de Linus torvalds) e até então, nada do Hurd se apresentar... Mais de dezesseis anos depois do lançamento do livro Open Life, e o Hurd ainda não demonstra nem sinais de lançamento de uma versão estável. Não adianta acreditarem que o micrkernel é algo mais poderoso focado simplesmente no isolamento do kernel e carecendo de recursos.
Não dá para debater todos os recursos aqui neste artigo pois, como
Michael Kerrisk descreve em seu livro Linux programing Interface, são mais de 500 system calls e library functions e acredito que tudo isso já serviu de uma boa abordagem para entender como Linux é poderoso.
https://www.linuxbnb.net/home/adding-a-system-call-to-linux-arm-architecture/