OS5は、勉強のためにフルスクラッチで作成しているOSです。ブートローダー・カーネル・ユーザーランド(カーネル上で動作するアプリケーション群)を含んでいます。現在の主なスペックは以下の通りです。
現状、一番作りこめているのはカーネルで、カーネルが持つべき主要な機能を一通り揃えています。カーネルが持つ機能について図1.1に示します。
スモールスタートとして、シンプルに割り切って実装するようにしています。図1.1に示す一通りの機能を備えたカーネルが2000行程度で、ブートローダーとユーザーランドを合わせても3000行程度で実現できています(そのため、「本にしてみよう」と思い立ちました)。
機能実装の節目でブログ記事を公開しており、記事公開の日付をバージョン番号にしています。これまでのリリース情報など、OS5の情報は以下のページにまとめています。なお、本書で対象とするバージョンは2017年1月現在の最新リリースであるblog-20170123です*1。
[*1] ただし、1行80文字に収まるよう修正しています。
また、ソースコードはGitで管理しており、GitHub上にリポジトリがあります。
blog-20170123時点で、ソースコード行数(アセンブラとCの行数の総和)は、表1.1の通りとなりました。
項目 | 行数 |
---|---|
ブートローダー | 328 |
カーネル | 2117 |
ユーザーランド | 541 |
"OS5"という名前は、「OS作り5回目」を示しています(過去に"OS"、"OS2"、"OS3"、"OS4"がありました)。これまで、Linux 0.01のソースコードから分岐してみたり、本を参考にしてみたりしていましたが、どのやり方もしっくりこない思いがあり、途中でやめてしまいました。ただし、「OSを作りたい」という思いは変わらなかったため、色々とやり方を変えて試していました。
5回目にして、「いい加減、フルスクラッチでできるのではないか」と思い、2015年3月頃からフルスクラッチで"OS5"の作成を始めました。今になって思えば、ソースコードや本などで「元となるOS」が存在した場合、それを改造しても「元のOS + 自分のパッチ」であり、「自分のOS」とは言いづらい事がダメだったのかなと思います。
OS5のソースディレクトリ構成は以下の通りです。
以降の章では、boot、kernel、apps、toolsの各ディレクトリのソースコードを説明します。
ソースディレクトリ直下のMakefileについては、章を割くほどでもないので、この章で掲載します。内容は以下の通りです。
1: all: fd.img 2: 3: fd.img: boot/boot.bin kernel/kernel.bin apps/apps.img 4: cat $+ > $@ 5: 6: boot/boot.bin: 7: make -C boot 8: 9: kernel/kernel.bin: 10: make -C kernel 11: 12: apps/apps.img: 13: make -C apps 14: 15: doc: 16: make -C doc 17: 18: clean: 19: make -C boot clean 20: make -C kernel clean 21: make -C apps clean 22: make -C doc clean 23: rm -f *~ *.o *.bin *.dat *.img *.map 24: 25: run: fd.img 26: qemu-system-i386 -fda $< 27: 28: .PHONY: boot/boot.bin kernel/kernel.bin apps/apps.img doc clean
Makefileの書き方として、特に独特なことはしていません。このMakefileは、下位のbootディレクトリやkernelディレクトリ、appsディレクトリのMakefileを呼び出します。そして、下位の各ディレクトリの生成物(boot/boot.bin、kernel/kernel.bin、apps/apps.img)を、catで結合し、fd.img(OS5のフロッピーディスクイメージ)を生成します(Makefileの3行目)。
メモリマップを図1.2に示します。図1.2は、実際にカーネルやユーザーランド(ファイルシステム)等をRAM上にどのように配置するかを示しています。0x0000 0500〜0x0009 FFFF(640KB)は「コンベンショナルメモリ(伝統的メモリ領域)」と呼ばれる領域で、x86 CPUにおいて古くからRAMに割り当たっていたメモリ領域です。
なお、カーネルやアプリケーションは「仮想アドレス空間」というアドレス空間で動作します。物理アドレス空間と分けることで、「アプリケーションは必ず同じアドレスから始まる」といったことや、「アプリケーションはカーネルの空間にアクセスさせない」といったことを実現しています。詳しくはkernel/memory.cで説明します。