Olá a todos, estamos compartilhando com vocês a segunda parte da publicação “Sistemas de arquivos virtuais no Linux: por que são necessários e como funcionam?” Você pode ler a primeira parte
Como monitorar VFS usando ferramentas eBPF e Cco
A maneira mais fácil de entender como o kernel opera nos arquivos sysfs
é ver na prática, e a maneira mais fácil de assistir ARM64 é usar eBPF. eBPF (abreviação de Berkeley Packet Filter) consiste em uma máquina virtual rodando em query
) na linha de comando. As fontes do kernel informam ao leitor o que o kernel pode fazer; executar as ferramentas eBPF em um sistema carregado mostra o que o kernel está realmente fazendo.
Felizmente, começar a usar o eBPF é bastante fácil com a ajuda de ferramentas bcc
são scripts Python com pequenas inserções de código C, o que significa que qualquer pessoa familiarizada com as duas linguagens pode modificá-los facilmente. EM bcc/tools
Existem 80 scripts Python, o que significa que muito provavelmente um desenvolvedor ou administrador de sistema poderá escolher algo adequado para resolver o problema.
Para ter pelo menos uma ideia superficial do trabalho que os VFSs fazem em um sistema em execução, tente vfscount
ou vfsstat
. Isto mostrará, digamos, que dezenas de chamadas vfs_open()
e “seus amigos” acontecem literalmente a cada segundo.
vfsstat.py
é um script Python com inserções de código C que simplesmente conta chamadas de função VFS.
Vamos dar um exemplo mais trivial e ver o que acontece quando inserimos uma unidade flash USB em um computador e o sistema a detecta.
Usando o eBPF você pode ver o que está acontecendo em
/sys
quando uma unidade flash USB é inserida. Um exemplo simples e complexo é mostrado aqui.
No exemplo mostrado acima, bcc
ferramenta sysfs_create_files()
. Nós vemos que sysfs_create_files()
foi lançado usando kworker
stream em resposta ao fato de a unidade flash ter sido inserida, mas qual arquivo foi criado? O segundo exemplo mostra o poder do eBPF. Aqui trace.py
Imprime um backtrace do kernel (opção -K) e o nome do arquivo que foi criado sysfs_create_files()
. A inserção de instrução única é um código C que inclui uma string de formato facilmente reconhecível fornecida pelo script Python que executa o LLVM compilador just-in-time. Ele compila esta linha e a executa em uma máquina virtual dentro do kernel. Assinatura de função completa sysfs_create_files ()
deve ser reproduzido no segundo comando para que a string de formato possa se referir a um dos parâmetros. Erros neste trecho de código C resultam em erros reconhecíveis do compilador C. Por exemplo, se o parâmetro -l for omitido, você verá "Falha ao compilar o texto BPF". Os desenvolvedores familiarizados com C e Python encontrarão as ferramentas bcc
fácil de expandir e mudar.
Quando a unidade USB for inserida, o backtrace do kernel mostrará que o PID 7711 é um thread kworker
que criou o arquivo «events»
в sysfs
. Assim, a chamada de sysfs_remove_files()
mostrará que a remoção da unidade resultou na exclusão do arquivo events
, que corresponde ao conceito geral de contagem de referência. Ao mesmo tempo, visualizar sysfs_create_link ()
com eBPF ao inserir o drive USB mostrará que pelo menos 48 links simbólicos foram criados.
Então, qual é o objetivo do arquivo de eventos? Uso disk_add_events ()
, e também "media_change"
Ou "eject_request"
pode ser gravado em um arquivo de evento. Aqui, a camada de bloco do kernel informa ao espaço do usuário que um “disco” apareceu e foi ejetado. Observe como esse método de pesquisa é informativo ao inserir uma unidade USB, em comparação com a tentativa de descobrir como as coisas funcionam puramente a partir da fonte.
Sistemas de arquivos raiz somente leitura permitem dispositivos incorporados
É claro que ninguém desliga o servidor ou o computador puxando o plugue da tomada. Mas por que? Isso ocorre porque os sistemas de arquivos montados em dispositivos de armazenamento físico podem ter gravações atrasadas e as estruturas de dados que registram seu estado podem não estar sincronizadas com as gravações no armazenamento. Quando isso acontece, os proprietários do sistema precisam esperar até a próxima inicialização para iniciar o utilitário. fsck filesystem-recovery
e, na pior das hipóteses, perda de dados.
No entanto, todos sabemos que muitos dispositivos IoT, bem como roteadores, termostatos e carros, agora rodam Linux. Muitos desses dispositivos têm pouca ou nenhuma interface de usuário e não há como desligá-los de forma “limpa”. Imagine ligar um carro com a bateria descarregada quando a energia da unidade de controle é fsck
quando o motor finalmente começa a funcionar? E a resposta é simples. Dispositivos incorporados dependem do sistema de arquivos raiz ro-rootfs
(sistema de arquivos raiz somente leitura)).
ro-rootfs
oferecem muitos benefícios que são menos óbvios que a autenticidade. Uma vantagem é que o malware não pode gravar /usr
ou /lib
, se nenhum processo Linux puder escrever lá. Outra é que um sistema de arquivos amplamente imutável é fundamental para o suporte em campo de dispositivos remotos, uma vez que o pessoal de suporte depende de sistemas locais que são nominalmente idênticos aos sistemas de campo. Talvez o benefício mais importante (mas também o mais insidioso) seja que o ro-rootfs força os desenvolvedores a decidir quais objetos do sistema serão imutáveis na fase de design do sistema. Trabalhar com ro-rootfs pode ser estranho e doloroso, como as variáveis const costumam ser nas linguagens de programação, mas seus benefícios justificam facilmente a sobrecarga adicional.
criação rootfs
Somente leitura requer algum esforço extra para desenvolvedores incorporados, e é aí que o VFS entra em cena. O Linux exige que os arquivos estejam em /var
eram graváveis e, além disso, muitos aplicativos populares que executam sistemas embarcados tentarão criar configurações dot-files
в $HOME
. Uma solução para arquivos de configuração no diretório inicial geralmente é pré-gerá-los e compilá-los em rootfs
. Para /var
Uma abordagem possível é montá-lo em uma partição gravável separada, enquanto /
montado somente leitura. Outra alternativa popular é usar montagens de ligação ou sobreposição.
Suportes conectáveis e empilháveis, seu uso em contêineres
Execução do comando man mount
é a melhor maneira de aprender sobre montagens vinculáveis e sobrepostas, que oferecem aos desenvolvedores e administradores de sistema a capacidade de criar um sistema de arquivos em um caminho e depois expô-lo a aplicativos em outro. Para sistemas embarcados, isso significa a capacidade de armazenar arquivos em /var
em uma unidade flash somente leitura, mas um caminho de montagem sobreposto ou vinculável de tmpfs
в /var
ao carregar, permitirá que os aplicativos escrevam notas ali (rabisco). Na próxima vez que você ativar as alterações em /var
será perdido. Uma montagem sobreposta cria uma união entre tmpfs
e o sistema de arquivos subjacente e permite fazer alterações ostensivas nos arquivos existentes em ro-tootf
enquanto uma montagem vinculável pode esvaziar novas tmpfs
pastas visíveis como graváveis em ro-rootfs
caminhos. Enquanto overlayfs
esse é o certo (proper
) tipo de sistema de arquivos, a montagem vinculável é implementada em
Com base na descrição da sobreposição e da montagem conectável, ninguém fica surpreso que mountsnoop
de bcc
.
Desafio system-nspawn
inicia o contêiner durante a execução mountsnoop.py
.
Vamos ver o que aconteceu:
Lançar mountsnoop
enquanto o contêiner está "inicializando" mostra que o tempo de execução do contêiner é altamente dependente da montagem que está sendo vinculada (apenas o início da saída longa é mostrado).
é systemd-nspawn
fornece arquivos selecionados em procfs
и sysfs
host para contêiner como caminhos para ele rootfs
... Além de MS_BIND
sinalizador que configura a montagem de ligação, alguns outros sinalizadores na montagem definem o relacionamento entre as alterações nos namespaces do host e do contêiner. Por exemplo, uma montagem vinculada pode pular alterações em /proc
и /sys
no contêiner ou oculte-os dependendo da chamada.
Conclusão
Compreender o funcionamento interno do Linux pode parecer uma tarefa impossível, já que o próprio kernel contém uma enorme quantidade de código, deixando de lado as aplicações do espaço do usuário Linux e as interfaces de chamada de sistema em bibliotecas C, como glibc
. Uma maneira de progredir é ler o código-fonte de um subsistema do kernel, com ênfase na compreensão das chamadas do sistema e dos cabeçalhos do espaço do usuário, bem como das principais interfaces internas do kernel, como tabelas file_operations
. As operações de arquivo fornecem o princípio “tudo é um arquivo”, tornando-as particularmente agradáveis de gerenciar. Arquivos de origem do kernel C no diretório de nível superior fs/
apresentam uma implementação de sistemas de arquivos virtuais, que são uma camada wrapper que fornece compatibilidade ampla e relativamente simples entre sistemas de arquivos populares e dispositivos de armazenamento. Vincular e montar sobreposição por meio de namespaces Linux é a mágica do VFS que torna possível a criação de contêineres somente leitura e sistemas de arquivos raiz. Combinado com um exame do código-fonte, a ferramenta principal eBPF e sua interface bcc
tornando a exploração do núcleo mais fácil do que nunca.
Amigos, escrevam, este artigo foi útil para vocês? Talvez você tenha algum comentário ou observação? E quem tiver interesse no curso de Administrador Linux está convidado a
Fonte: habr.com