- Banan-OS ist ein in C++ geschriebenes Hobby-Betriebssystem und unterstützt derzeit die Architekturen x86_64 und i686
- Der Funktionsumfang umfasst Ring3-User-Space, SMP, einen Netzwerk-Stack, ELF-Laden und dynamisches Linken, Copy-on-Write-Speicher sowie eine grundlegende grafische Umgebung
- Unterstützt werden bei Treibern und Systemfunktionen NVMe- und ATA-Datenträger, NICs der Reihen E1000/E1000E und RTL, PS2- und USB-Eingabe, die Dateisysteme Ext2 und FAT, GRUB sowie ein eigener BIOS-Bootloader
- TCP ist als teilweise implementiert und fehlerhaft gekennzeichnet; SSL, virtio-Geräte, einige USB-Controller, die Dateisysteme Sys und 9P sowie ein eigener UEFI-Bootloader sind noch nicht implementiert
- Das Bauen erfolgt hauptsächlich über das Skript
./bos; nach dem Erstellen der Toolchain sind QEMU- und Bochs-Starts, Kernel- und Image-Builds sowie die Auswahl von Architektur-, Bootloader-, UEFI- und initrd-Optionen möglich
Überblick über Banan-OS
- Banan-OS ist ein in C++ geschriebenes Hobby-Betriebssystem
- Derzeit unterstützte Architekturen sind x86_64 und i686
- Eine Live-Demo ist unter bananymous.com/banan-os verfügbar
- Um DOOM auszuführen, muss man mit dem Befehl
start-guiin die GUI-Umgebung wechseln und dann im GUI-Terminaldoomstarten
Wichtige implementierte Funktionen
- Allgemeine Funktionen
-
Ring3-User-Space
- SMP, also Multiprocessing
- linearer Framebuffer auf Basis von VESA und GOP
- Netzwerk-Stack
- Laden von ELF-Executables
- partieller AML-Interpreter
- grundlegende grafische Umgebung
- Terminal-Emulator
- Statusleiste
- Programmstarter
- „Anständige Apps“ sind noch nicht implementiert
- ELF Dynamic Linking
- Copy-on-Write-Speicher
- File Mapping ist implementiert
- anonyme Mappings sind nicht implementiert
-
Unterstützung für Treiber, Netzwerk und Dateisysteme
- Treiber
- Unterstützt NVMe-Datenträger sowie ATA-IDE-/SATA-Datenträger
- Unterstützt E1000-, E1000E- und RTL8111/8168/8211/8411-NICs
- PS2-Tastaturen unterstützen alle Scancode-Sets, PS2-Mäuse werden ebenfalls unterstützt
- USB unterstützt xHCI, Tastaturen, Mäuse, Massenspeicher und Hubs
- EHCI, OHCI, UHCI sowie virtio-Netzwerk- und Speichergeräte sind nicht implementiert
- Netzwerk
- Unterstützt ARP, ICMP, IPv4 und UDP
-
TCP ist teilweise implementiert und fehlerhaft
- Unix-Domain-Sockets werden unterstützt
- SSL ist nicht implementiert
- Dateisysteme
- Unterstützt virtuelles Dateisystem, Ext2, FAT12/16/32, Dev, Ram und Proc
- Sys und 9P sind nicht implementiert
- Bootloader
- Unterstützt GRUB und einen eigenen BIOS-Bootloader
- Ein eigener UEFI-Bootloader ist noch nicht implementiert
Codestruktur
- Jede Hauptkomponente und Bibliothek hat ein eigenes Unterverzeichnis wie
kernel,userspaceoderlibc - Jedes Verzeichnis enthält ein
include-Verzeichnis mit allen Header-Dateien der Komponente - Alle Header werden über absolute Pfade eingebunden
Build und Ausführung
- Unter Ubuntu 22.04 werden über
aptdie Paketebuild-essential,git,ninja-build,texinfo,bison,flex,libgmp-dev,libmpfr-dev,libmpc-dev,parted,qemu-system-x86,cpu-checkerbenötigt - In einer
pacman-Umgebung werdenbase-devel,git,wget,cmake,ninja,parted,qemu-system-x86benötigt - Die Toolchain für das Betriebssystem wird einmalig mit
./bos toolchaingebaut- Da dabei binutils und gcc kompiliert werden, kann das längere Zeit dauern
- Das Builden und Ausführen des OS selbst erfolgt mit dem Befehl
./bos./bos qemu./bos qemu-nographic./bos qemu-debug./bos bochs
- Es ist auch möglich, nur den Kernel oder nur das Disk-Image zu bauen
./bos kernel./bos image
- Zum Erstellen und Ändern von Disk-Images sind Root-Rechte erforderlich
Build-Optionen und Image-Verwaltung
- Für Builds auf einer anderen Architektur muss die Umgebungsvariable
BANAN_ARCHgesetzt werden- Beispiel:
BANAN_ARCH=i686
- Beispiel:
- Zum Wechseln des Bootloaders muss die Umgebungsvariable
BANAN_BOOTLOADERgesetzt werden- Unterstützte Werte sind
BANANundGRUB
- Unterstützte Werte sind
- Für den Start im UEFI-Modus muss
BANAN_UEFI_BOOT=1gesetzt werdenOVMF_PATHmuss ebenfalls auf den korrekten OVMF-Pfad gesetzt werden; der Standardwert ist/usr/share/ovmf/x64/OVMF.fd
- Um ein initrd-Image ohne physisches Root-Dateisystem zu erstellen, muss
BANAN_INITRD=1gesetzt werden- Das kann beim Testen auf Hardware mit nicht unterstützten USB-Controllern verwendet werden
- Wenn das Disk-Image beschädigt ist oder ein neues Image erstellt werden soll, kann man
build/banan-os.imglöschen oder./bos image-fullausführen - Ein Shell-Completion-Skript für zsh wird ebenfalls bereitgestellt
- Die Datei
_script/shell-completion/zsh/_boskann nach/usr/share/zsh/site-functions/kopiert werden, oder_script/shell-completion/zshwird in der.zshrczufpathhinzugefügt
- Die Datei
Wie man beiträgt
- Das Upstream-Projekt wird nicht auf GitHub, sondern unter
https://git.bananymous.com/Bananymous/banan-osgehostet - GitHub-PRs können ebenfalls gesendet werden, aber der Maintainer muss den Diff herunterladen und manuell anwenden
- Es ist auch möglich, einen Account auf dem separaten Git-Server zu erhalten; dafür sollte man per E-Mail oder Discord Kontakt aufnehmen
- Für neue Funktionen wird bevorzugt, zuerst den Maintainer zu kontaktieren
- Da es sich um ein Lernprojekt handelt, kann ein PR für eine Funktion, die der Maintainer selbst umsetzen wollte, ohne vorherige Absprache geschlossen werden
- Bugfixes sind immer willkommen
- Commit-Messages müssen in der ersten Zeile das Format
Subject: DescriptionhabenSubjectbezeichnet den geänderten Bereich, etwaKernel,ShelloderBuildSystem- Die erste Zeile muss innerhalb von 72 Zeichen bleiben
- Der Hauptteil sollte die Änderungen und deren Gründe zusätzlich erläutern
- Alle Commits müssen die in
.pre-commit-config.yamldefinierten pre-commit hooks bestehen
1 Kommentare
Meinungen auf Hacker News
Wirklich cool, und der Name gefällt mir auch. Ich frage mich, was von dem, was du bisher implementiert hast, der schwierigste Teil war, und ob es zwischendurch ernsthafte Hindernisse gab.
Der AML-Interpreter war schwierig, weil die ACPI-Spezifikation so furchtbar chaotisch geschrieben ist; USB war anstrengend, weil die Spezifikation sehr umfangreich ist und viele Querverweise enthält.
Große Hindernisse gab es keine, aber bei manchen Features habe ich erst aufgegeben und bin ein oder zwei Monate später wieder darauf zurückgekommen.
Wirklich cool. Besonders beeindruckend ist, dass du den USB-Treiber von Grund auf implementiert hast. Nebenbei: Ich habe versucht, es mit
cat doom1.wadkaputtzumachen.Bei der Ankündigung eines neuen Betriebssystem-Kernels gibt es einen Satz, der traditionell enthalten sein muss, aber in dieser Ankündigung fehlt er.
Cool. Mich würde interessieren, wie viele Stunden pro Woche du ungefähr in dieses Projekt steckst. Der Arbeitsaufwand wirkt beträchtlich.
In deinem Profil steht, dass du Student bist; heißt das, du studierst an einer Uni? Falls ja, hast du dieses OS auch direkt im Rahmen deines Studiums behandelt?
Ansonsten ist dieses Projekt nicht direkt Teil meines Studiums. Allerdings habe ich durch das Projekt auch einen Teilzeitjob im Embedded-Bereich der Uni bekommen.
Wie viel Zeit ich investiere, hängt wirklich davon ab, was im Leben gerade los ist. In manchen Monaten waren es insgesamt nur 5 Stunden, in manchen Wochen fast 40 Stunden.
Ein cooles Projekt. Als Name für einen Fork wäre PlatanOS auch nicht schlecht.
Sehr schön, und es sieht nach viel Arbeit aus. Mich würde interessieren, welche Herausforderung dir besonders in Erinnerung geblieben ist.
Großartig. Mich würde interessieren, wie du entwickelst. Läuft es in einer VM oder auf echter Hardware? Wie sieht der Ablauf aus, wenn du dich hinsetzt und mit der Arbeit beginnst?
Du musst dabei viel gelernt haben; mich würde auch interessieren, wie du Notizen machst oder die Entwicklung nachverfolgst. Oder ist das OS selbst so etwas wie ein lebendes Entwicklungstagebuch?
Es ist immer toll zu sehen, wie es auf echtem Bare Metal läuft, und Bare Metal ist nicht so nachsichtig wie eine VM.
Normalerweise entscheide ich mich für ein Feature, das ich hinzufügen möchte, überfliege grob die relevanten Spezifikationen und schaue mir manchmal auch an, wie bestehende Betriebssysteme damit umgehen. Dann baue ich mir im Kopf ein Modell davon, was das System braucht, und schreibe den Code so, wie er mir in dem Moment einfällt.
Ich habe die wirklich schlechte Angewohnheit, keine Dokumentation oder Notizen zu schreiben. Im Grunde behalte ich alles im Kopf und vergesse es später, wenn ich die Information brauche. Für Komplexeres zeichne ich manchmal Diagramme und schreibe Notizen, aber die bewahre ich fast nur lokal auf.
Mich würde interessieren, wo man bei Treibern wie NVMe, ATA oder Realtek-NICs überhaupt anfängt. Bei Maus und Tastatur weiß ich, dass sie den Standard HID verwenden, aber haben andere Geräte auch ähnliche Standardprotokolle?
Ist das der Grund, warum Linux in den meisten Fällen eine „Treiberinstallation“ vermeiden kann? Und wenn es Standard-Geräte-APIs gibt, warum durchläuft Windows dann jedes Mal einen Treiberinstallationsprozess, wenn man etwas anschließt?
Für alle Geräte, für die ich Treiber geschrieben habe, waren die Spezifikationen frei verfügbar. NVMe findet man zum Beispiel unter https://nvmexpress.org/specifications.
Wie Linux oder Windows Treiber genau handhaben, weiß ich nicht gut. Beim Kompilieren des Linux-Kernels legt man fest, welche Treiber in den Kernel aufgenommen werden und welche als Module bleiben. Übliche Treiber werden normalerweise zusammen mit dem Kernel gebaut, sodass man sie später kaum installieren muss; man lädt einfach das Treibermodul.
Außerdem gibt es Geräte, die mit einem generischen Treiber funktionieren, mit einem spezifischen Treiber aber mehr Funktionen bieten. Zum Beispiel LED-Einstellungen bei einer Gaming-Maus. Windows installiert vermutlich solche optionalen Treiber.
Ein sehr cooles Nebenprojekt. Hast du Tipps für Leute, die etwas Ähnliches versuchen wollen, etwa wo man anfangen sollte oder welche Referenzen gut sind?
Hervorragend. Mit dieser Funktionsausstattung hätte ich nicht gerechnet. Planst du, künftig noch mehr Software zu portieren?
Lokal habe ich noch ein paar Ports, die noch nicht funktionieren.
git,binutils,gccundmakekompilieren alle, werfen aber seltsame Fehler. Vermutlich liegt es an Bugs in meinerlibcoder bei den Systemaufrufen.