- Maestro é um projeto para criar do zero, em Rust, um sistema operacional leve do tipo Unix que seja compatível com Linux o suficiente para uso cotidiano
- Começou em 2018 como um projeto escolar e, inicialmente, foi implementado em linguagem C, mas migrou para Rust por causa de problemas de manutenção da base de código e das exigências de segurança no desenvolvimento de kernels
- Atualmente é um kernel monolítico para x86 de 32 bits, com 135 das 437 chamadas de sistema do Linux implementadas em algum grau, cerca de 31%
- Também estão sendo desenvolvidos o sistema de boot e gerenciador de daemons Solfège, utilitários de sistema e o gerenciador de pacotes blimp; musl, bash e parte dos GNU coreutils já funcionam
- Ainda está em estágio muito inicial e é instável; como os testes se concentram em QEMU, VMWare e VirtualBox, é mais seguro não instalá-lo em máquinas com dados importantes
Objetivos e ponto de partida do Maestro
- Maestro é um sistema operacional do tipo Unix escrito do zero em Rust
- O objetivo é criar um sistema leve e suficientemente compatível com Linux para poder ser usado no dia a dia
- Ele nasceu da vontade de criar um ambiente em que fosse possível entender diretamente o sistema de A a Z e personalizá-lo da forma desejada
Por que a migração de C para Rust
- O primeiro commit foi feito em 22 de dezembro de 2018, às 03:18, e o projeto começou como um trabalho escolar
- A implementação inicial avançou por cerca de um ano e meio em linguagem C, mas ficou difícil manter a base de código limpa
- Vantagens obtidas ao recomeçar em Rust
- Possibilidade de redesenhar o projeto desde o início com base no que foi aprendido com erros anteriores
- Possibilidade de tentar algo mais novo do que simplesmente reescrever em C um kernel parecido com o Linux
- Graças ao sistema de tipos do Rust, parte da responsabilidade pela segurança de memória pode ficar com o compilador, e não com o programador
Onde Rust se mostrou vantajoso no desenvolvimento de kernel
- Depurar o desenvolvimento de um kernel é muito mais difícil do que depurar uma aplicação comum
- É difícil encontrar documentação, e a própria implementação do BIOS pode ter defeitos
- Durante o boot, o kernel tem acesso a toda a memória e pode escrever até em locais incorretos, como o próprio código
- Não é possível usar ferramentas como valgrind para rastrear vazamentos de memória
- gdb pode ser usado com QEMU e VMWare, mas o comportamento do kernel pode variar dependendo do emulador ou da máquina virtual
- Também há ambientes que não suportam gdb, como o VirtualBox, e o suporte a gdb no QEMU e no VMWare é incompleto em alguns pontos; às vezes o próprio gdb também trava
- Para reduzir esses problemas, uma linguagem com segurança de memória é vantajosa também no desenvolvimento de kernels
- Rust ajudou a inserir várias salvaguardas no kernel e é considerado a melhor decisão do projeto
Estado atual da implementação
- O Maestro atualmente é um kernel monolítico e suporta apenas a arquitetura x86 de 32 bits
- Estado da implementação no momento da escrita
- 135 de 437 chamadas de sistema do Linux foram implementadas em algum grau
- Taxa de implementação das chamadas de sistema: {p:31}
- Somando todo o repositório, há 615 arquivos e 48.800 linhas de código
- A contagem de linhas foi calculada com o comando
cloc
- Componentes do sistema operacional além do kernel
- Solfège: sistema de boot e gerenciador de daemons, de certa forma parecido com o systemd, mas mais leve
- maestro-utils: conjunto de comandos de utilitários de sistema
- blimp: gerenciador de pacotes
- Outros componentes estão disponíveis publicamente no GitHub
- Software de terceiros cujo funcionamento foi confirmado
- Biblioteca padrão C musl
-
bash
- Alguns comandos dos GNU coreutils, como
ls,cat,mkdir,rm,rmdir,unameewhoami - Como o neofetch original não conhece o Maestro, é necessária uma versão de neofetch com patch
- Alguns comandos dos GNU coreutils, como
Como testar diretamente e limitações
- O sistema operacional ainda está em um estágio muito inicial e é muito instável
- Não é recomendado instalá-lo em uma máquina que contenha dados importantes
- Até agora, ele foi testado principalmente em QEMU, VMWare e VirtualBox
- Há duas formas de instalação
- Baixar um arquivo
.isocompactado já compilado - Compilar a ISO diretamente
- Baixar um arquivo
- A ISO inclui o instalador do sistema operacional e pode ser executada em QEMU, VMWare, VirtualBox etc.
- Para executar a ISO, é preciso RAM suficiente, e 1 GB é o bastante
- Isso porque os pacotes a instalar são armazenados na RAM do initramfs, e não no disco
- Atualmente, o sistema operacional não consegue ler diretamente um pendrive USB ou CD-ROM, então depende do bootloader
Temas que o texto vai abordar
- O objetivo não é escrever um tutorial de criação de sistemas operacionais
- Como materiais básicos sobre criação de sistemas operacionais, são recomendados osdev.org e o blog de Philipp Oppermann
- Daqui em diante, serão abordados temas mais avançados, processos de resolução de problemas e como computadores, sistemas operacionais e a internet funcionam internamente
Próximos rumos de desenvolvimento
- As prioridades são organizar a base de código e otimizar desempenho
- Como começou como um projeto escolar, houve partes em que foram tomados atalhos para cumprir prazos, e é preciso pagar essa dívida técnica acumulada
- Alguns vazamentos de memória também precisam ser corrigidos, e a otimização de desempenho pode virar tema de texto
- O próximo grande objetivo é fazer o gerenciador de pacotes funcionar completamente em cima do sistema operacional
- É necessário suporte a rede, que está em desenvolvimento atualmente
- É necessário suporte a bibliotecas compartilhadas
- Bibliotecas compartilhadas precisam mapear arquivos diretamente na memória, mas a implementação atual da chamada de sistema
mmapno kernel não oferece suporte a isso
- Depois disso, será possível instalar e testar com mais facilidade programas como gcc/g++, clang, rustc, make, Git e Vim
- O objetivo final é chegar a um fluxo de desenvolvimento do kernel em cima do próprio Maestro
Processo de desenvolvimento para aumentar a maturidade do kernel
- O desenvolvimento avança executando programas no kernel e, se eles não funcionam, identificando a chamada de sistema responsável para implementá-la ou corrigi-la
- Executar o programa no kernel
- Se não funcionar, observar a saída das chamadas de sistema e encontrar a primeira chamada de sistema que causa o problema
- Se essa chamada de sistema não estiver implementada ou tiver um bug, implementá-la ou corrigi-la
- Executar o programa novamente
- Quanto mais programas funcionarem corretamente no kernel, mais estável e completo o kernel se torna
1 comentários
Opiniões no Hacker News
Muito obrigado pelo apoio; isso significa muito, porque dediquei bastante esforço a este projeto.
Parece que o site está bem lento ou fora do ar agora; há mais tráfego do que eu esperava e também suspeito de um ataque DoS.
Estou no trabalho no momento, então é difícil me concentrar nisso agora, mas, quando chegar em casa, vou tentar fazer funcionar melhor.
Em 2010, quando Rust ainda não existia, logo depois de me formar na faculdade, mexi um pouco em um OS hobby do tipo Unix em C, e foi muito divertido.
Tenho inveja de você ter conseguido arranjar tempo para chegar até aqui.
A barra de navegação ocupa cerca de 33% da tela e não dá para removê-la.
Não entendo por que as pessoas fixam esse tipo de coisa e tomam um espaço precioso de leitura. Se eu quiser, consigo rolar para o topo em uns 300 ms.
É um projeto pequeno e bacana. É surpreendente que ele consiga inicializar até esse ponto sem ter implementado nem um terço das chamadas de sistema do Linux.
Mas é provável que o que falta sejam as partes mais complexas. Por exemplo, a camada TTY parece estar em um nível bem básico agora, e fazê-la direito deve dar bastante trabalho.
Por isso, é difícil esperar que o Maestro rode aplicações Linux nos próximos 3 anos. Mesmo sem considerar os milhares de drivers que o Linux tem.
Plataformas maduras acumulam lógica para dar suporte a vários cenários, então a maioria dos casos acaba não precisando da maior parte do sistema como um todo.
É parecido com a frase: “ninguém usa mais de 10% do Excel, mas os 10% que cada pessoa usa são diferentes”.
Implementando só 30% das funções do Excel, provavelmente daria para criar um engine capaz de abrir 99% das planilhas existentes no mundo. Mas, se você quiser compatibilidade completa de documentos, ainda há um longo caminho pela frente.
Algumas chamadas de sistema só são invocadas em determinados caminhos de código, ou podem ser chamadas novas necessárias apenas quando se mira em um kernel mais recente.
Há muitas chamadas de sistema, e algumas delas são bem obscuras. Uma reimplementação totalmente aberta acabaria tendo de oferecer suporte à maioria delas, mas um terço é um bom começo.
[1] Eu queria rodar a VM em bare metal ou inicializar como uma VM, e, tirando algo como
init=/path/to/the/vm, isso parecia o caminho de menor esforço para chegar lá. Mas essa abordagem não me daria o que eu realmente queria: colocar os drivers de hardware e a pilha TCP dentro da linguagem da VM.Acho que não é preciso rodar Steam, LibreOffice e Firefox para que isso seja útil. Muitos componentes de uma arquitetura comum de servidores ou microsserviços fazem coisas relativamente simples, e poderiam se beneficiar bastante de um kernel seguro e simples.
Também existe o Kerla, um kernel monolítico feito em Rust que mirava compatibilidade com a ABI do Linux. Mas parece estar dormente há alguns anos.
[1] https://news.ycombinator.com/item?id=28986229
Ele tem uma arquitetura de microkernel e provavelmente está um pouco mais maduro. Como é licenciado sob MIT, parece haver alguma margem para compartilhamento de código.
Só pelo fato de ser feito em Rust, seria interessante fazer testes de segurança/testes de invasão/fuzzing para ver se um hacker competente consegue encontrar alguma coisa.
Tenho 100% de certeza de que fuzzing ou testes de invasão revelariam muitos problemas. Ainda não tive tempo para dedicar a isso.
Parece algo que já foi tentado no projeto Kerla, que agora está descontinuado.
Parece um projeto interessante. Mas acho que as desvantagens de usar C e as dificuldades do desenvolvimento de OS estão principalmente na parte de depuração.
Ao mudar para Rust, certos tipos de erros de memória devem ter desaparecido, mas depurar ainda é doloroso? Ou ficou menos sofrido a ponto de ser tolerável?
Depurar ainda é doloroso, mas muito menos do que antes.
Por exemplo, não é muito provável esquecer de usar um mutex, porque o compilador avisa com um erro.
Mas ele não é uma solução mágica, e problemas como deadlocks ainda existem. Especialmente quando entram interrupções no meio.
Por exemplo, se você bloqueia um mutex e ocorre uma interrupção, o código que bloqueou aquele mutex fica parado até a interrupção terminar. Mas, se o código de tratamento da interrupção tentar bloquear o mesmo mutex, surge um deadlock, e o sistema de tipos não consegue ajudar com esse problema.
A solução é desabilitar o tratamento de interrupções enquanto o mutex estiver bloqueado, mas o compilador não consegue impor isso.
Fugindo um pouco do assunto, gostei do Gource que o autor usou no vídeo de contribuições.
Eu nunca tinha visto antes, mas alguns anos atrás tive a ideia de tentar fazer algo parecido. Parece que realmente não existem ideias totalmente novas.
Gosto muito da ideia de criar o próprio kernel, especialmente para fins de aprendizado. Fiquei curioso sobre quais materiais você usou para entender kernels e OS em geral.
Fiquei surpreso que o Theseus OS não tenha sido mencionado. É um OS em desenvolvimento feito do zero em Rust, que usa as garantias de segurança de memória do compilador Rust para oferecer automaticamente muitas coisas que, em um OS tradicional, precisariam ser cuidadosamente conectadas.
Por exemplo, ele é seguro mesmo com uma estrutura de nível único de privilégio e espaço de endereçamento único. Todas as partes do OS podem ser hot-plugged.
A desvantagem é que todo código nativo precisa ser Rust, mas no ano passado foi implementado um runtime WASM. Thread relacionado de 3 anos atrás:
https://news.ycombinator.com/item?id=25741729
Não imaginei que haveria alguém louco o suficiente para encarar o projeto ft_penguin. Ainda não sei se esse era mesmo o nome, mas, sinceramente, mandou muito bem.
Quando eu estava na escola, 7 anos atrás, achava que era um dos projetos com a pior relação entre recompensa e tempo necessário.
Fiquei curioso se você começou com um amigo, como era antes de reescrever em Rust, e se fez outros projetos ao mesmo tempo.
Olhar o código me trouxe lembranças de como era divertido, e agora fiquei com vontade de largar o trabalho em DevOps e voltar ao que eu pretendia fazer originalmente: embarcados ou outros trabalhos de baixo nível.