借り初めのひみつきち

仮ブログです。

Rust 自作 OS 日記/Part 6 過去最大の更新

このシリーズの記事は月1くらいで書こうと思ってて前回からそんなに日付も経ってないのですが、 ここ最近で過去最大にいろいろ変わってしまったので前倒しで書くことにします。

initrd

某はりぼて OS では起動時にフロッピーディスクの内容をメモリに転送して RAM ディスクのように使います。 これ自体は特別珍しい仕様でもなく、 Linux などでも起動に必要なファイルをまとめたイメージを RAM ディスクとして読み込んで臨時ルートファイルシステムとして使う仕組みがあります。

というわけで myos も起動時にカーネルと一緒に initrd.img というファイルを RAM ディスクとして読み込む機能を実装しました。

f:id:neriring16:20201112095241p:plain

myos は UEFI から起動するのでファイルを読み込む処理自体はカーネルの読み込みと同じように簡単に実装でき、セクションの再配置等をしなくて済む分カーネルの読み込みよりも簡単です。 ブートローダーの変更点はイメージファイルをメモリに読み込む処理と読み込んだアドレスをカーネルに教える数行程度です。

ファイルシステム

ファイルシステムにおける重要な概念として、ブロックデバイスとキャラクタデバイスがあります。 ブロックデバイスは本来ブロック単位で入出力するデバイスを指していて近年の定義ではバッファリングされるデバイスを指すようですが、実際にはファイルシステムが構築されるストレージを想定した概念です。 キャラクタデバイスは本来は主に文字単位で入出力するデバイスを指していて近年の定義ではバッファリングされないデバイスを指すようで、コンソール端末やシリアルポートなどが典型的なキャラクタデバイスになります。 ブロックとキャラクタどちらにも分類されない(できない)デバイスもあると思いますが、通常ブロックデバイスに含まれないデバイスは一般にキャラクタデバイスに分類されます。変な話ですね。 ブロックデバイスに対してファイルシステムとして見える形でアクセスできるようにする操作をマウントと言います。

initrd をサポートするにあたり、メモリ上の特定の領域をブロックデバイスに見せかけてアクセスするドライバ (いわゆる RAM ディスク) と、簡易的な FAT ファイルシステムのドライバを実装しました。

Rust では常に所有権を意識してオブジェクトを扱う必要がありますが、ファイルシステムは誰が何を所有するかというのが結構難しく、 また myos では非同期 I/O を採用する予定ですがこちらも管理や設計が難しく、現在はその辺が仮実装となっています。

アプリケーションの実行

ファイルが読み込みできるようになったのでアプリの実行もできるようにしてみました。

f:id:neriring16:20201113000947p:plain

myos は某はりぼて OS と直接関連はありませんが、 API の数が少なく実装が比較的容易そうだったので実装してみました。 はりぼて OS エミュレーター(Haribote Os Emulator) の頭文字をとって HOE という名前にしました。 現在は 2/3 程度の API が実装され、半分くらいのアプリは動作しているようです。 なお、某はりぼて OS のアプリは大抵圧縮されてますが、現状 myos では圧縮アプリに非対応なので非圧縮版のバイナリを入手する必要があります。

Personality

HOE 対応にあたり、ネイティブタスクのスレッドと HOE 上で動作しているタスクを区別してコンテキスト管理できるようにスレッドに Personality を設定できるようにしました。 API を実行する際はスレッドに紐づけられた Personality から HOE ランタイムのインスタンスを取得し、各種ハンドルの変換やアプリ固有のデータはこのインスタンスを通じて管理します。

まだかなり汚い仮実装のところも多いですが、とりあえずアプリが動くようになって画面が賑やかになりました。

しかし 64bit のカーネルからセグメントをバリバリ使う 32bit アプリを呼び出すためかなり特殊な処理が多くなってしまいました。 いずれ本体の開発が落ち着いたら CPU エミュレーターでも作って対応した方がいいかもしれません(対応するとは言ってない