OSを作り始める前に、どんな機能を作るのか、どのようなソースコードの構成になるのかをざっくりと把握しておきましょう。
本書で実装する機能
本書で作るOSは、大きく分けて次の機能を持ちます。
- マルチタスク: プロセスの切り替えを行い、複数のプログラムが同時に動作している (ように見せかける) 機能
- 例外ハンドラ: 実行時エラーなどのCPUがOSの介入を必要とするイベントを処理する機能
- ページング: 各プロセスごとの独立したメモリ空間を実現
- システムコール: アプリケーションからOSの機能を呼び出す機能
- デバイスドライバ: ディスクの読み書きなど、ハードウェアを操作する機能
- ファイルシステム: ディスク上のファイルを管理する機能
- コマンドラインシェル: 利用者がコマンドを入力してOSの機能を呼び出せる機能
本書で実装しない機能
逆に何が欠けているのかというと、主に次のような主要機能が省かれています。
- 割り込み処理: 「デバイスに新しいデータがないか定期的にチェックする」方式 (ポーリング) で実装されています。
- タイマー処理: プリエンプティブマルチタスクは実装されません。各プロセスが自発的にCPUを譲る、協調的マルチタスクで実装されています。
- プロセス間通信: プロセス間でデータをやり取りする機能は実装されません。
- マルチプロセッサ対応: シングルプロセッサのみ対応です。
もちろん、これらの機能は後から実装可能です。本書の実装を済ませた後に、HinaOSなどを参考にしながら実装してみると良いでしょう。
ソースコードの構成
ゼロからゆっくり作っていきますが、最終的には次のようなファイル構成になります。
├── disk/ - ファイルシステムの中身
├── common.c - カーネル・ユーザー共通ライブラリ: printf関数やmemset関数など
├── common.h - カーネル・ユーザー共通ライブラリ: 各種構造体・定数などの定義
├── kernel.c - カーネル: プロセス管理、システムコール、デバイスドライバ、ファイルシステム
├── kernel.h - カーネル: 各種構造体・定数などの定義
├── kernel.ld - カーネル: リンカスクリプト (メモリレイアウトの定義)
├── shell.c - コマンドラインシェル
├── user.c - ユーザー用ライブラリ: システムコールの呼び出し関数など
├── user.h - ユーザー用ライブラリ: 各種構造体・定数などの定義
├── user.ld - ユーザー: リンカスクリプト (メモリレイアウトの定義)
└── run.sh - ビルドスクリプト
本書中では「ユーザーランド」を略して「ユーザー」と表記していることがあります。ざっくり「アプリケーション側」という意味で捉えると分かりやすいでしょう。