HN no ar: Banan-OS, um sistema operacional tipo Unix escrito do zero
(github.com/Bananymous)- Banan-OS é um sistema operacional hobby escrito em C++, que atualmente oferece suporte às arquiteturas x86_64 e i686
- O escopo de recursos inclui espaço de usuário Ring3, SMP, pilha de rede, carregamento de ELF e ligação dinâmica, memória copy-on-write e até um ambiente gráfico básico
- Drivers e funções do sistema oferecem suporte a discos NVMe e ATA, NICs das famílias E1000/E1000E e RTL, entrada PS2 e USB, sistemas de arquivos Ext2 e FAT, além de GRUB e um bootloader BIOS próprio
- O TCP é marcado como implementado parcialmente e com bugs, enquanto SSL, dispositivos virtio, alguns controladores USB, os sistemas de arquivos Sys e 9P, e um bootloader UEFI próprio ainda não foram implementados
- O build é centrado no script
./bos, permitindo após criar a toolchain executar QEMU ou Bochs, compilar o kernel e a imagem, e escolher opções de arquitetura, bootloader, UEFI e initrd
Visão geral do Banan-OS
- Banan-OS é um sistema operacional hobby escrito em C++
- As arquiteturas suportadas atualmente são x86_64 e i686
- Uma demonstração ao vivo está disponível em bananymous.com/banan-os
- Para executar DOOM, é preciso entrar no ambiente GUI com o comando
start-guie depois executardoomno terminal da interface gráfica
Principais recursos implementados
- Recursos gerais
-
Espaço de usuário Ring3
- SMP, ou multiprocessamento
- framebuffer linear baseado em VESA e GOP
- pilha de rede
- carregamento de executáveis ELF
- interpretador AML parcial
- ambiente gráfico básico
- emulador de terminal
- barra de status
- lançador de programas
- “apps decentes” ainda não implementados
- ligação dinâmica de ELF
- memória copy-on-write
- mapeamento de arquivos implementado
- mapeamento anônimo não implementado
-
Suporte a drivers, rede e sistemas de arquivos
- Drivers
- Suporta discos NVMe e discos ATA IDE/SATA
- Suporta NICs E1000, E1000E e RTL8111/8168/8211/8411
- O teclado PS2 suporta todos os conjuntos de scancode, e o mouse PS2 também é suportado
- USB oferece suporte a xHCI, teclado, mouse, armazenamento em massa e hubs
- EHCI, OHCI, UHCI e dispositivos de rede/armazenamento virtio não foram implementados
- Rede
- Suporta ARP, ICMP, IPv4 e UDP
-
TCP é implementado parcialmente e tem bugs
- Suporta Unix domain socket
- SSL não foi implementado
- Sistema de arquivos
- Suporta sistema de arquivos virtual, Ext2, FAT12/16/32, Dev, Ram e Proc
- Sys e 9P não foram implementados
- Bootloader
- Suporta GRUB e um bootloader BIOS próprio
- O bootloader UEFI próprio ainda não foi implementado
Estrutura do código
- Cada componente principal e biblioteca tem um subdiretório separado, como
kernel,userspaceelibc - Cada diretório contém um diretório
includecom todos os arquivos de cabeçalho do componente - Todos os headers são incluídos com caminhos absolutos
Build e execução
- No Ubuntu 22.04, são necessários via
aptos pacotesbuild-essential,git,ninja-build,texinfo,bison,flex,libgmp-dev,libmpfr-dev,libmpc-dev,parted,qemu-system-x86ecpu-checker - Em ambientes com
pacman, são necessáriosbase-devel,git,wget,cmake,ninja,partedeqemu-system-x86 - A toolchain para o sistema operacional precisa ser compilada apenas uma vez com
./bos toolchain- Como isso compila binutils e gcc, pode levar bastante tempo
- O build e a execução do próprio SO são feitos com o comando
./bos./bos qemu./bos qemu-nographic./bos qemu-debug./bos bochs
- Também é possível compilar apenas o kernel ou a imagem de disco
./bos kernel./bos image
- São necessários privilégios de root para criar ou modificar imagens de disco
Opções de build e gerenciamento de imagem
- Para compilar para outra arquitetura, defina a variável de ambiente
BANAN_ARCH- Exemplo:
BANAN_ARCH=i686
- Exemplo:
- Para trocar o bootloader, defina a variável de ambiente
BANAN_BOOTLOADER- Os valores suportados são
BANANeGRUB
- Os valores suportados são
- Para executar com UEFI, é preciso definir
BANAN_UEFI_BOOT=1OVMF_PATHtambém deve apontar para o caminho correto do OVMF, com valor padrão/usr/share/ovmf/x64/OVMF.fd
- Para criar uma imagem initrd sem sistema de arquivos root físico, defina
BANAN_INITRD=1- Isso pode ser útil ao testar em hardware com controladores USB não suportados
- Se a imagem de disco estiver corrompida ou se quiser criar uma nova imagem, apague
build/banan-os.imgou execute./bos image-full - Também é fornecido um script de shell completion para zsh
- Copie o arquivo
_script/shell-completion/zsh/_bospara/usr/share/zsh/site-functions/, ou adicione_script/shell-completion/zshaofpathdo.zshrc
- Copie o arquivo
Como contribuir
- O upstream não é hospedado no GitHub, e sim em
https://git.bananymous.com/Bananymous/banan-os - Também é possível enviar PRs pelo GitHub, mas o maintainer precisa baixar o diff e aplicá-lo manualmente
- Também é possível obter uma conta no servidor git separado; nesse caso, é preciso entrar em contato por email ou Discord
- Para adicionar novos recursos, a forma preferida é entrar em contato primeiro com o maintainer
- Como é um projeto com foco em aprendizado, um PR com um recurso que o maintainer pretendia implementar pessoalmente pode ser fechado se for enviado sem consulta prévia
- Correções de bugs são sempre bem-vindas
- A primeira linha da mensagem de commit deve seguir o formato
Subject: DescriptionSubjectdeve indicar a área alterada, comoKernel,ShellouBuildSystem- A primeira linha deve caber em até 72 caracteres
- O corpo deve explicar adicionalmente o que mudou e por quê
- Todos os commits devem passar pelos pre-commit hooks definidos em
.pre-commit-config.yaml
1 comentários
Comentários no Hacker News
Muito legal, e gostei do nome. Fiquei curioso para saber qual foi a parte mais difícil do que você implementou até agora, e se houve algum obstáculo sério no caminho.
O interpretador AML foi difícil porque a especificação ACPI é escrita de um jeito muito bagunçado, e USB foi trabalhoso porque a especificação é enorme e tem muitas referências cruzadas.
Não houve grandes obstáculos, mas algumas funcionalidades eu abandonei por um tempo e voltei a elas um ou dois meses depois.
Muito legal. Em especial, é impressionante ter implementado um driver USB do zero. A propósito, tentei quebrar digitando
cat doom1.wad.Há uma frase que, por tradição, precisa aparecer no anúncio de um novo kernel de sistema operacional, mas ela está faltando neste anúncio.
Legal. Fiquei curioso sobre quantas horas por semana você dedica a este projeto. A quantidade de trabalho parece considerável.
No seu perfil diz que você é estudante; isso quer dizer universitário? Se sim, você também trabalhou diretamente neste OS como parte dos estudos?
Fora isso, o projeto não fez parte diretamente dos meus estudos. Mas, graças a ele, também consegui um trabalho de meio período na área de embarcados da universidade.
O tempo investido varia muito conforme o que está acontecendo na minha vida. Em alguns meses coloquei só umas 5 horas no total; em algumas semanas, quase 40 horas.
Projeto legal. Para um fork, PlatanOS também seria um bom nome.
Muito bom, e parece ter dado bastante trabalho. Fiquei curioso para saber quais foram os desafios mais marcantes.
Impressionante. Fiquei curioso sobre como você desenvolve. Você roda em uma VM ou em hardware real? Quando senta para trabalhar, como o processo acontece?
Você deve ter aprendido muito fazendo isso; também fiquei curioso sobre como faz anotações ou acompanha o desenvolvimento. Ou será que o próprio OS é uma espécie de diário de desenvolvimento vivo?
Ver rodando em bare metal de verdade é sempre legal, e o bare metal não é tão tolerante quanto uma VM.
Normalmente escolho uma funcionalidade que quero adicionar, dou uma olhada geral na especificação relacionada e, às vezes, vejo como sistemas operacionais existentes lidam com isso. Depois de formar um modelo mental do que o sistema precisa, escrevo o código conforme as ideias surgem ali na hora.
Tenho o péssimo hábito de não escrever documentação nem notas. Basicamente guardo tudo na cabeça e, quando preciso daquela informação depois, já esqueci. Para coisas mais complexas, às vezes faço diagramas e anotações, mas quase sempre ficam só localmente.
Fico pensando por onde se começa a escrever drivers como NVMe, ATA ou NIC Realtek. Sei que mouse e teclado usam HID, que é um padrão, mas será que outros dispositivos também têm protocolos padrão parecidos?
Também fico pensando se é por isso que o Linux consegue evitar “instalação de driver” na maioria dos casos, e por que, se há APIs padrão para dispositivos, o Windows ainda passa por um processo de instalação de driver quase toda vez que se conecta algo.
Todos os dispositivos para os quais escrevi drivers tinham especificações publicadas gratuitamente. Por exemplo, NVMe está em https://nvmexpress.org/specifications.
Não sei bem como Linux ou Windows lidam com drivers. Ao compilar o kernel Linux, você especifica quais drivers incluir no kernel e quais deixar como módulos. Em geral, drivers comuns são compilados junto com o kernel, então quase nunca é preciso instalá-los depois; basta carregar o módulo do driver.
Também há dispositivos que funcionam com um driver genérico, mas oferecem mais recursos quando existe um driver dedicado. Por exemplo, configurar os LEDs de um mouse gamer. O Windows provavelmente instala esse tipo de driver opcional.
Projeto paralelo muito legal. Você tem dicas para quem quer tentar algo parecido, como por onde começar ou quais materiais de referência são bons?
Excelente. Eu não esperava esse conjunto de funcionalidades. Fiquei curioso se há planos de portar mais software no futuro.
Localmente, tenho alguns ports que ainda não funcionam.
git,binutils,gccemaketodos compilam, mas estão gerando erros estranhos. Provavelmente é algum bug na minhalibcou nas chamadas de sistema.