2 pontos por GN⁺ 2024-12-06 | 1 comentários | Compartilhar no WhatsApp
  • 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-gui e depois executar doom no 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, userspace e libc
  • Cada diretório contém um diretório include com 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 apt os pacotes build-essential, git, ninja-build, texinfo, bison, flex, libgmp-dev, libmpfr-dev, libmpc-dev, parted, qemu-system-x86 e cpu-checker
  • Em ambientes com pacman, são necessários base-devel, git, wget, cmake, ninja, parted e qemu-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
  • Para trocar o bootloader, defina a variável de ambiente BANAN_BOOTLOADER
    • Os valores suportados são BANAN e GRUB
  • Para executar com UEFI, é preciso definir BANAN_UEFI_BOOT=1
    • OVMF_PATH també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.img ou execute ./bos image-full
  • Também é fornecido um script de shell completion para zsh
    • Copie o arquivo _script/shell-completion/zsh/_bos para /usr/share/zsh/site-functions/, ou adicione _script/shell-completion/zsh ao fpath do .zshrc

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: Description
    • Subject deve indicar a área alterada, como Kernel, Shell ou BuildSystem
    • 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

 
GN⁺ 2024-12-06
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.

    • Não houve nada excessivamente difícil, mas, se eu tivesse que escolher, seriam o interpretador AML ou a pilha USB.
      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.
    • No começo eu li como “banyan tree”, e só quando vi a arte ASCII percebi que era uma referência a banana.
  • Muito legal. Em especial, é impressionante ter implementado um driver USB do zero. A propósito, tentei quebrar digitando cat doom1.wad.

    • Obrigado. Quase não há serialização nos dados escritos no TTY, então alimentar isso com dados binários arbitrários pode quebrar mesmo :D
  • 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.

    • Você certamente está falando da frase “isto é um projeto de hobby e não será grande nem profissional como o GNU”, certo?
  • 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?

    • Sim, sou universitário. Mostrei o projeto a um professor e consegui “pular” algumas disciplinas, como Sistemas Operacionais e Concorrência.
      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.

    • Eu preferiria PlátanOS, com acento na primeira sílaba.
  • Muito bom, e parece ter dado bastante trabalho. Fiquei curioso para saber quais foram os desafios mais marcantes.

    • Acho que o maior desafio foi ler especificações grandes. Eu nunca tinha feito isso direito antes, então levou um tempo para me acostumar.
  • 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?

    • Cerca de 95% dos testes faço em uma VM. É muito mais rápido e muito mais conveniente. Mesmo assim, também testo regularmente em hardware real.
      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.

    • Basicamente, quase todos os dispositivos comuns têm protocolos padronizados. Mas também há dispositivos para os quais o fabricante precisa fornecer um driver.
      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?

    • É praticamente o mesmo que outras pessoas já disseram. Vale a pena ler https://wiki.osdev.org/Getting_Started e ter em mente que, se decidir desenvolver um sistema operacional, isso leva muito tempo.
    • Para conhecimento prático, use a OSDev Wiki; para teoria, livros de projeto de sistemas operacionais e arquitetura de computadores.
    • Para Rust, há https://os.phil-opp.com/; para desenvolvimento de sistemas operacionais em geral, há https://github.com/tuhdo/os01. E Operating Systems: Three Easy Pieces é leitura obrigatória.
  • Excelente. Eu não esperava esse conjunto de funcionalidades. Fiquei curioso se há planos de portar mais software no futuro.

    • Há planos de portar mais coisas. Eu não quero colocar código de terceiros no OS base, mas ports são uma ótima maneira de conseguir rodar coisas que ainda não escrevi eu mesmo.
      Localmente, tenho alguns ports que ainda não funcionam. git, binutils, gcc e make todos compilam, mas estão gerando erros estranhos. Provavelmente é algum bug na minha libc ou nas chamadas de sistema.