🍊

自作OS初心者によるmikanos写経日記

2021/12/13に公開

この記事は、自作OS Advent Calendar 2021/12/13 の記事として書かれました。

この記事について

「ゼロからのOS自作入門」 という本に沿って、教育用OS mikanos を写経(内容を理解する目的でソースコードを写すこと)した体験と、自分なりのTipsをまとめたものです。

自分なりに試行錯誤した経験をまとめたものですので、もちろんこのやり方を他の人に強制するものでは全くありません。

「ゼロからのOS自作入門」に出会うまで

筆者は職業エンジニアです。日頃はいわゆる「高レイヤー」なことをしています。例えばWebシステムなどを作るために、システム全体のアーキテクチャを検討したり、使用するミドルウェアの選定をしたり、少しプログラミングをしたりしています。
良いシステムを作るためにITの色々を勉強します。その勉強も高レイヤーのことが主です。「1秒間に100人の人がアクセスするとしたら、このシステムにはどのくらいのメモリが必要?」などを頑張って計算します。
ITの世界では様々な技術がレイヤーとして抽象化されており、そのおかげで高レイヤーな仕事をしていると、基盤として頑張ってくれている低レイヤーのことをあまり知らなくても何とかなってしまいます。OSはその代表的な例で、仕事でOSを使わない日はないのにOSがどのような仕組みで動いているかを知る必要はあまりありません。少なくともOSが何をしてくれるかを分かっていればOKです。OSはメモリ管理をしてくれるということだけ知っていれば、OSがどのようにメモリを管理しているのかは知らなくても大丈夫。
しかし、何年かエンジニアとして働く間に、「多分知らなくてもいいんだろうけど知りたいこと」が増えてきました。抽象化されたレイヤーに少しづつ綻びが見えるようになって、面白そうな下の方がチラチラと見えるようになりました。

Turing Complete FMという技術系Podcastの第8回でhikaliumさんが「30日でできる!OS自作入門」という本についてお話しされていて、その様子が本当に楽しそうだったことに衝撃を受け、低レイヤーをもっと知ることができたら毎日の高レイヤーな仕事がもっと楽しくなるんじゃないかと思いました。30日本も購入しましたが、そのすぐ後に出版されたuchanさんの「ゼロからのOS自作入門」が2021年に取り組むにはやりやすいと感じ、こちらを読み始めました。ソースコードがgit管理されていたりUSBからのブートに対応しているなど現代的であることに加え、発売直後から著者の方がDiscordで勉強会を開催されていたり、多くの人が記事を書かれていたりしたことも大きかったです。

写経の準備

○参照用リポジトリ
写経する元(お手本)を用意します。githubからmikanosをcloneします。

○写経用リポジトリ
これから写経して育てていく自分のリポジトリを作成します。mikanosの最新版に対して何らかの追加機能を実装するという目的ならば、github上でforkしたものをcloneして変更を加えていくというやり方も考えられますが、今回は1から写経するので空リポジトリを作成します。

写経のプロセス

写経はtagを単位として行います。gitのtagはcommitに対して分かりやすくするために作る別名です。mikanosにおいては"osbook_day04a"のように「ゼロからのOS自作入門」の本文に対応する名前で打たれています。

各tagごとに以下を繰り返します。

  1. git diffで次のtagまでの差分を眺める
  2. 講義ビデオを見る
  3. 「ゼロからのOS自作入門」本文を読む
  4. もう一度git diffを眺める
  5. 写経
    ex. Discord勉強会で質問

写経にたどり着くまでが長いです。大体8割くらいの時間を事前の理解(1~4)に費やすイメージです。tagは軽いものも重いものもあるのでtagあたりの時間は何とも言えませんが、私の場合は1章分(=数tag)の写経に12~22時間ほどかかります。

何も準備をせずに写経をやってみると分かるのですが、中身を理解していないコードを自分の手で書くというのは非常に不安になります。例えば読むだけならば半分くらいしか中身を理解していなくても大丈夫ですが、自分が書くとなると95%は理解した(つもり)でないと、なかなか耐えられるものではありません。そのため1行1行を詳細に調べるようになりました。これが写経のいいところです。

1. git diffで差分を眺める

参照用リポジトリで現在のtagと1つ先のtagの差分をgit diffで取り、更新されているファイルリストを出して1つ1つ中身を見ていきます。main.cppが更新されている場合は、まずそこから見ると良いと思います。

わからないところがたくさんありますが、このステップではとりあえずわからないところを全部リストアップします。眺めていて「とりあえず全部わからん」となっても、わからないところを言語化していく過程で結構理解が進みます。自分のリストを見返してみると以下のようなものが多いです。

  • そもそもの変更の目的、何の機能をOSに追加しようとしているのか
  • この関数は何をやっているのか?
  • この変数は何を格納しているのか?
  • C++の文法(知らないキーワードや書き方)

ひたすらリストを書いているとすごい量になりますが、ここで「分からない!」という気持ちを紙にぶつけておくことが大事です。

2. 講義ビデオを見る

Youtubeで著者の方が大学で行われた講義の内容が公開されています。「ゼロからのOS自作入門」(のドラフト)が題材になっており、本の内容が詳しく紹介されています。これは非常にありがたいです。ステップ1でわからないところをリストアップしていますが、ビデオを見て行く途中でそのわからないところがある程度解消されていきます。
ステップ2と3はどちらが先でもいいと思うのですが、自分はビデオを先に見る事が多いです。

注意としては本文の内容が全て講義で紹介されているわけではないです。たとえば9章と10章の説明はありません。その場合はこのステップを飛ばして本文を読みます。

3. 「ゼロからのOS自作入門」本文を読む

ビデオを先に見ていると、大体の内容や何を目的とした変更なのかは頭に入っています。上から順に読んでいくというよりはわからないリストの回答を探すように読んでいきます。ただ受動的に読んでいくと内容の難しさもあり眠くなってしまう事が多いのですが、この方法だと効率が良い気がします。

(必要な場合) C++について調べる

mikanosでは様々なC++の機能が使われています。筆者はCを少し勉強した事がある程度だったので山ほどわからないキーワードが出てきました。ビデオや本文でも大事なところは解説されているのですが、コードに初出のタイミング(章)で必ず取り上げられるわけではないので、そういう時は自分で調べます。

○本で調べる
新・明解C++入門

ネットにも良い解説はたくさんありますが、この本は素晴らしいです。OS自作のためにC++のことを調べるときは、確保した変数がメモリ上でどうなっているかなども含めて理解する必要がありますが、その辺りもきちんと図解されています。

mikanosの前半を理解するために特に役に立った箇所

  • 6-2 参照
  • 12-3 演算子関数に関する規則
  • 14-1 コンストラクタとデストラクタ
  • 14-2 代入演算子とコピーコンストラクタ

ちなみに自分は中級編も買いましたが、わからないことを調べたときはほとんど入門編に答えが載っていたので、mikanosの副読本として買うならば入門編だけでいいと思います。

○ネットで調べる
osbook_day09a の window.hpp でコピーコンストラクタやコピー代入演算子と共にdefault/deleteなどのキーワードが出てきます。
この辺りを理解するにはC++11でクラスを定義した際に暗黙的に定義される6種類のメンバ関数の制御について知る必要があります。以下のページがわかりやすいです。
関数のdefault/delete宣言

4. もう一度git diffを眺める

ここまで調べたことを元に、もう一度diffを見てみます。この時点で必要な知識は揃っているので、主に頭の中を整理する作業です。
込み入った内容を扱う章では、図を書くこともあります。自分的には9章の内容がかなりややこしく、追加されたクラス間の継承関係、LayerクラスとWindowクラスの各関数の呼び出しの順番、LayerManager.UpDownのロジックなどをぐりぐり書きました。

5. 写経

参照用リポジトリと写経用リポジトリを横に並べて写していきます。写経といいつつ、できるだけ自分で考えたコードであるかのように取り組みます。

  • このtagでやろうとしていることをさらに分割できるか考える
  • 分割した単位で写経をし、ビルド・実行が通ることを確認してcommitする
  • main.cppから始めて、呼び出しの順に写していく
  • 分からないコード、なくても動くのでは?というコードは写さない

特に最後の点は大切にしています。なくても動くのではと思ったコードを省いたらビルドが通らなくて、調べたら理由がわかるということもありますし、そのまま通ることもあります。もしかしたらそのコードは次の章で必要で、ここで省いたせいで次の章でうまく動かないかもしれません。でもそのほうがいいと思います。分からずに写したコードがうまく働くよりも、分からないところを省いて後で動かなくなったほうが、なぜ必要だったかを理解できるからです。

ex. Discord勉強会で質問

毎週土曜日の21時からDiscordで著者の方によるもくもく会(現在は雑談会)が開かれていて、mikanosに関する質問をする事ができます。

似たような質問が前にされているかもしれないので、質問の前に調べます。

  • Discordのチャット履歴を検索
  • サポートwikiのFAQを確認
  • サポートwikiのIssuesを検索

Discordで質問をする際は、以下の要素で文章を構成します。

  • 質問が関係する箇所(本文の図番号やコードのtag)
  • 質問そのもの(簡潔な文章で)
  • 質問の背景
  • 自分の思考プロセスや仮説
  • ログや実施コマンド(あれば)

こちらの会にはとてもお世話になっています。「ゼロからのOS自作入門」を読む方の中にはプログラミングをした事が無い方、Linuxを触ったことのない方から、低レイヤーの経験が豊富な方まで様々いらっしゃいますが、どのような質問にもフラットに答えてくださいます。とても良い雰囲気の会だと思います。

終わりに

筆者はゆっくりと進めているので写経完了までまだまだですが、一旦自分なりのプロセスをまとめてみました。

「ゼロからのOS自作入門」は分量(744ページ!)、内容ともに手軽に読み終えられる本ではありません。しかし本文の構成も工夫されており、WikiやDiscord勉強会などのサポートも手厚く、とても読み手のことを考えて作られた本だと感じています。私も引き続き腰を据えてじっくりと取り組んでいきたいと思いますので、この記事が同じように頑張るみなさんの参考になれば幸いです。

Discussion