HN公開: 一から書かれたUnix系OS「Banan-OS」
(github.com/Bananymous)- Banan-OSはC++で書かれたホビーOSで、現在はx86_64とi686アーキテクチャをサポート
- 機能範囲には、Ring3ユーザー空間、SMP、ネットワークスタック、ELFローディング・動的リンク、copy-on-writeメモリ、基本的なグラフィカル環境まで含まれる
- ドライバとシステム機能は、NVMe・ATAディスク、E1000/E1000EおよびRTL系NIC、PS2・USB入力、Ext2・FATファイルシステム、GRUBおよび独自BIOSブートローダをサポート
- TCPは部分実装でバグありとされており、SSL、virtioデバイス、一部のUSBコントローラ、Sys・9Pファイルシステム、独自UEFIブートローダは未実装
- ビルドは
./bosスクリプトを中心に進められ、ツールチェーン作成後にQEMU・Bochsの実行、カーネル・イメージのビルド、アーキテクチャ・ブートローダ・UEFI・initrdオプションの選択が可能
Banan-OS概要
- Banan-OSはC++で書かれたホビーOS
- 現在サポートしているアーキテクチャはx86_64とi686
- ライブデモはbananymous.com/banan-osで提供されている
- DOOMを実行するには、
start-guiコマンドでGUI環境に入り、その後GUIターミナルでdoomを実行する必要がある
実装済みの主な機能
- 一般機能
-
Ring3ユーザー空間
- SMP、つまりマルチプロセッシング
- VESAとGOPベースの線形フレームバッファ
- ネットワークスタック
- ELF実行ファイルのロード
- 部分的なAMLインタプリタ
- 基本的なグラフィカル環境
- ターミナルエミュレータ
- ステータスバー
- プログラムランチャー
- 「まともなアプリ」はまだ未実装
- ELF動的リンク
- copy-on-writeメモリ
- ファイルマッピングは実装済み
- 匿名マッピングは未実装
-
ドライバ・ネットワーク・ファイルシステム対応
- ドライバ
- NVMeディスクとATA IDE/SATAディスクをサポート
- E1000、E1000E、RTL8111/8168/8211/8411 NICをサポート
- PS2キーボードはすべてのscancode setをサポートし、PS2マウスにも対応
- USBはxHCI、キーボード、マウス、大容量記憶装置、ハブをサポート
- EHCI、OHCI、UHCI、virtioネットワーク・ストレージデバイスは未実装
- ネットワーク
- ARP、ICMP、IPv4、UDPをサポート
-
TCPは部分実装でバグあり
- Unix domain socketをサポート
- SSLは未実装
- ファイルシステム
- 仮想ファイルシステム、Ext2、FAT12/16/32、Dev、Ram、Procをサポート
- Sysと9Pは未実装
- ブートローダ
- GRUBと独自BIOSブートローダをサポート
- 独自UEFIブートローダはまだ未実装
コード構造
- 各主要コンポーネントとライブラリは、
kernel、userspace、libcのような個別のサブディレクトリを持つ - 各ディレクトリには、コンポーネントのすべてのヘッダファイルを収める
includeディレクトリがある - すべてのヘッダは絶対パスでincludeされる
ビルドと実行
- Ubuntu 22.04基準で、
aptパッケージとしてbuild-essential、git、ninja-build、texinfo、bison、flex、libgmp-dev、libmpfr-dev、libmpc-dev、parted、qemu-system-x86、cpu-checkerが必要 pacman環境ではbase-devel、git、wget、cmake、ninja、parted、qemu-system-x86が必要- OS用ツールチェーンは一度だけ
./bos toolchainでビルドする- binutilsとgccをコンパイルするため時間がかかる場合がある
- OS自体のビルドと実行は
./bosコマンドで行う./bos qemu./bos qemu-nographic./bos qemu-debug./bos bochs
- カーネルまたはディスクイメージだけをビルドすることもできる
./bos kernel./bos image
- ディスクイメージの生成・修正にはroot権限が必要
ビルドオプションとイメージ管理
- 別アーキテクチャ向けにビルドするには、
BANAN_ARCH環境変数を設定する- 例:
BANAN_ARCH=i686
- 例:
- ブートローダを切り替えるには、
BANAN_BOOTLOADER環境変数を設定する- サポートされる値は
BANANとGRUB
- サポートされる値は
- UEFIで起動するには、
BANAN_UEFI_BOOT=1を設定する必要があるOVMF_PATHも正しいOVMFパスに設定する必要があり、デフォルト値は/usr/share/ovmf/x64/OVMF.fd
- 物理rootファイルシステムなしでinitrdイメージを作るには、
BANAN_INITRD=1を設定する- 未対応のUSBコントローラを持つハードウェアでテストする際に使える
- ディスクイメージが破損した、または新しいイメージを作りたい場合は、
build/banan-os.imgを削除するか./bos image-fullを実行する - zsh用のshell completionスクリプトも提供されている
_script/shell-completion/zsh/_bosファイルを/usr/share/zsh/site-functions/にコピーするか、_script/shell-completion/zshを.zshrcのfpathに追加する
貢献方法
- アップストリームはGitHubではなく
https://git.bananymous.com/Bananymous/banan-osでホストされている - GitHub PRも送れるが、メンテナがdiffをダウンロードして手動で適用する必要がある
- 専用のgitサーバーアカウントを受け取ることもでき、その場合はメールまたはDiscordで連絡する必要がある
- 新機能の追加は、まずメンテナに連絡する方式が好まれる
- 学習目的のプロジェクトであるため、メンテナが自分で実装しようとしていた機能を事前相談なしにPRで送るとクローズされる可能性がある
- バグ修正は常に歓迎される
- コミットメッセージの1行目は
Subject: Description形式で書く必要があるSubjectはKernel、Shell、BuildSystemのように変更箇所を表す- 1行目は72文字以内に収める必要がある
- 本文では変更内容と理由を追加で説明する必要がある
- すべてのコミットは
.pre-commit-config.yamlで定義されたpre-commit hookを通過する必要がある
1件のコメント
Hacker Newsのコメント
本当に素晴らしいし、名前も気に入った。これまで実装した中で最も難しかった部分は何だったのか、途中で深刻な障害もあったのか気になる
ACPI仕様があまりにひどく書かれていたのでAMLインタプリタが難しく、USBは仕様の分量が多く相互参照も多かったので大変だった
大きな障害はなかったが、ある機能はいったん諦めて、1〜2か月後にまた戻って進めることもあった
本当にすごい。特にUSBドライバを一から実装した点がすごい。ちなみに
cat doom1.wadと入力して壊してみた新しいOSカーネルの発表には慣例的に入るべき一文があるが、この発表にはその文が抜けている
すごい。週に何時間くらいこのプロジェクトに使っているのか気になる。投入された作業量はかなり多そう
プロフィールには学生とあるけれど、大学生という意味なのか、もしそうなら学業の一部としてもこのOSを直接扱ったのか気になる
それ以外では、このプロジェクトが学業に直接含まれているわけではない。ただ、このプロジェクトのおかげで大学の組み込み系でパートタイムの仕事も得られた
投入時間は、その時々で生活に何が起きているかによって本当に変わる。ある月は合計5時間しか入れなかったし、ある週はほぼ40時間近くやったこともある
いいプロジェクトだ。フォーク名なら PlatanOS もよさそう
とても良く、作業量も多そう。特に印象に残っている課題は何だったのか気になる
すごい。開発はどんなふうにしているのか気になる。VMで動かしているのか、実機で動かしているのか、座って作業を始めると工程がどう流れるのか知りたい
これをやりながら多くを学んだはずだが、メモや開発の追跡はどうしているのかも気になる。あるいはOSそのものが生きた開発日誌のようなものなのかも気になる
実際のベアメタルで動くのを見るのはいつでも素晴らしいし、ベアメタルはVMほど寛容ではない
たいてい追加したい機能を決めてから関連仕様をざっと眺め、既存のOSがどう処理しているかも時々見る。システムに何が必要かの頭の中のモデルを作ったうえで、その場で思いつくままにコードを書く
ドキュメントやメモを書かないという本当に悪い癖がある。基本的に全部頭の中に入れておき、後でその情報が必要になったときに忘れている。より複雑なものについては図を描いたりメモを書いたりすることもあるが、ほとんどローカルにだけ保管している
NVMe、ATA、Realtek NICのようなドライバは、いったいどこから書き始めるのか気になる。マウスとキーボードは標準のHIDを使うのは分かるが、他のデバイスにも似たような標準プロトコルがあるのか気になる
Linuxがほとんどの場合「ドライバのインストール」を避けられる理由がこれなのか、標準デバイスAPIがあるならWindowsはなぜ何かを挿すたびにドライバのインストール手順を踏むのかも気になる
自分がドライバを書いたデバイスは、どれも仕様が無料で公開されていた。たとえばNVMeは https://nvmexpress.org/specifications にある
LinuxやWindowsがドライバをどう扱っているかはよく知らない。Linuxカーネルをコンパイルするとき、どのドライバをカーネルに含め、どれをモジュールにするかを指定する。普通、よく使われるドライバはカーネルと一緒にビルドされるので後からインストールする必要はほとんどなく、ドライバモジュールをロードするだけでよい
また、汎用ドライバでも動くが、専用ドライバがあればより多くの機能を使えるデバイスもある。たとえばゲーミングマウスのLED設定のようなものだ。Windowsはおそらくこうした任意のドライバをインストールしているのだと思う
とても素晴らしいサイドプロジェクトだ。似たようなことに挑戦したい人に、どこから始めるべきか、参考資料は何が良いかといったコツがあるのか気になる
素晴らしい。こういう機能構成は予想していなかった。今後さらに多くのソフトウェアを移植する予定があるのか気になる
ローカルにはまだ動作しないポートがいくつかある。
git、binutils、gcc、makeはすべてコンパイルできるが、奇妙なエラーを出している。おそらく自分のlibcかシステムコール側のバグである可能性が高い