💪

カーネルことはじめ

2023/12/10に公開

この記事は未踏ジュニアAdvent Calendar : 10日目です.

カーネル, 書きたくないですか?

こんにちは, horizon (@horizon2k38)です.
私は2023年の未踏ジュニアA9Nというマイクロカーネルを作成していました.
人類なら誰しもがカーネルを書きたいと思ったことがあるはずです. そんな方のために, 未踏期間で得られた "0からカーネルを如何にして学び, 実装したか" という知見をより一般化して解説しようと思います.
この記事の内容をすべて達成することで, あなたもきっとカーネルを書くことができるでしょう.

やれば出来る きっと 絶対 私No.1

注: この記事はどちらかといえば初心者向けなので, 自信がある方は最下部の"参考文献"と, 私が書いた低レイヤー学習のロードマップのみ読むことをおすすめします.

カーネル/OSとは

そもそもカーネルとは, 所謂OSの最核心を成すプログラムを指します.

モダンオペレーティングシステム p.3[1]では,

大半のコンピュータユーザはOSを触った経験を持っているが, OSとは何かを正しく把握することは難しい.
その問題の一部は, OSは, 基本的に互いに関係のない2つの役割を果たしているからである.
それはマシン拡張の役割とリソースマネージャとしての役割である.

とあります. カーネルが下のレイヤーを抽象化し, うまくリソースマネジメントをしてくれているおかげで, あなたはコンピューターを操作し, 様々なアプリケーションを立ち上げることができている というわけです. この記事が読めているのもまた同様でしょう.

勘の良い人は, ここでカーネルとOSが混合した表記になっていることを気付くと思います.
カーネルとOS, 2つを分ける違いは一体何でしょうか?
両者の区別には, 大きく分けて二種類の分類[2]が存在します.

狭い意味でのOS

  • カーネルはOSであり, OSはカーネルである.
    • 要するに同じものを指す.

広い意味でのOS

  • カーネルを使用して, ユーザーに直接見えるものとして具現化したものがOS.
    • カーネル + システムアプリケーション = OS

ピンと来ていない方も居るでしょう. このような場合, 実例を確認するのが最も最適です.

カーネル/OSの代表例

OS名 カーネル名
Windows NT Kernel (ntoskrnl.exe)
macOS XNU
Ubuntu Linux
Android Linux

上記の表は, 一般的にOSとして知られているものと, そのカーネルを対応付けたものです.
先程の"広い意味"として言うのなら, UbuntuとAndroidの違いはLinuxカーネルを使用するシステム・プログラムのみ ということになります.
(注: 厳密にはカスタムされているため, 同一とは言い切れない)

カーネルの学び方

概略を掴めたところで, 本題に入っていきましょう.

注: 以下の順番通りに私が学んだわけではありません. 紆余曲折したうえで, 初心者に向けるならというテーマで作成したロードマップです.

まずは基礎から

いきなりカーネルのソースコードを読もうとしても, 何をしているか理解できず途方に暮れてしまうことでしょう. 何故なら基礎となる理論が理解出来ていないからです.
理論と実装は表裏一体です. 両者ともに学ぶ必要がありますが, 一体どこからスタートしたら良いのでしょうか?

1. モダンオペレーティングシステム[1:1]

多くの大学でOSの教科書として使用されてきたのがこの書籍です.
最初はその厚さに驚くでしょうが, 内容を自分の読める範囲に分割することにより, 少しずつ読み進められるはずです.
まずあなたが読むべきなのは, この書籍の 第一章 : オペレーティングシステムの概要 です.
カーネル/OSの歴史や種類, 仕組みの概要が記述されています.
ここで重要なのは, 理論や実装をあくまでも概要として知ることができる点です. ここで取っ掛かりを掴みましょう.
二章以降はまだ読まなくてもよいです.

2. ゼロからのOS自作入門[3]

C++でx86_64向けのモノリシックなOS : MikanOSを実装するための書籍です.
ここではあなた自身の手を動かし, 実際に実装を行いましょう.
目を通すのと実際にコードを書いてみるのは大きな差があります. コードを書くためにキーボードを叩くのは当然ながら読むよりも時間を消費するからです.
1行毎にコードが意味するものを考えつつ実装することで, 読むだけでは気付けなかった疑問を抱くでしょう.
その疑問を記憶するかメモしておき, とりあえず完成させましょう.
注意としては, ブートローダー周りの優先度は低くてもOKです. 理論は知っておくべきですが, まだ実装に詳しく触れる必要はありません.

3. 再びモダンオペレーティングシステムへ

  1. で抱いた疑問のうち, ハードウェアに依存しないものは基本的に記載されています.
  • プロセスが理解できなかった.
  • ページングは結局どのような仕組みなのだろう?
  • 割り込みってなんなの?

といった, 2. で曖昧なままにしておいた疑問のリストを一つ一つ解消させて行きましょう.
その過程で二冊を比較しつつ読むことにより, 理解を深めることができます.
ここで重要なのは, 自分で実装するとしたらということを考えながら学習する必要があるということです. 浅い理解から深い理解へ変化させる必要があります.

4. OSDev Wiki[4]

  1. の疑問リストから, x86_64ハードウェア依存部分の謎を解き明かしていきましょう.
  • MikanOSのコンテキストスイッチはなぜあのような実装だったのだろう?
  • ページングは理解した. では, MikanOSではなぜあのような実装だったのだろう?
  • x86_64の割り込みはどのように処理される?

といった, より具体的な疑問を解き明かす必要があります. OSDev Wikiには実装例などの理解を深めるために使用可能なリソースが豊富に存在します. 理解できていない箇所と照らし合わせながら学習しましょう.

5. はじめて読む486[5]

  1. へ進む前に, これを読みましょう. x86アーキテクチャの学習に使用可能な書籍ですが, 名著と呼ばれているだけあって素晴らしいものです.
    ページングは言わずもがなですが, セグメントは使わないと思いきや使うことになる (CPU Local Variable)のでよく覚えておきましょう.

6. Intel SDM[6]

x86_64アーキテクチャをさらに深く知りたいのならば, Intel SDMという開発者マニュアルを読むことをおすすめします. これを読むのはつらいのですが, 必ず読むことになります. ここは気合でなんとかしてください.
全てを読む必要はありません (というか, 無理). 必要な部分だけでよいです.

7. 詳解Linuxカーネル[7]

疑問を解消してステップアップするごとに新たな疑問が生じます. そんな疑問を解消するのに有用なのが詳解Linuxカーネルです.
メインとしてx86/x86_64向けの実装を学習することができ, 自分はA9N開発中に何度も助けられました.

重要ポイント

  • 理解できていない箇所を放置しても結局学習することになる.
  • 理論->実装->理論->実装->... のループを回すことが重要.
  • なるほど! が多ければ多いほど良い.

実装しよう

このステップまで来たあなたには, "自分でも実装できるかも?" といったある種の自信を得ることができたはずです.
頑張りましょう.
アーキテクチャ選定のおすすめはRISC-Vですが, x86_64の方が情報が多く書きやすいかもしれません.
好きな方を選ぶと良いでしょう.
(自分はx86_64を選択して後悔しました).

ブート

ここまでは一切触れて来ませんでしたが, ブートローダーを実装したい場合, 以下のような文献がおすすめです.

リンカ・ローダ実践開発テクニック[2:1]

ELF(Executable and Linkable Format), リンカ, ローダについて学習することができます.
カーネル/OSを実装する上で, カーネルやアプリケーションのロードには欠かせないものになっています.
"ブート" カテゴリに入れていますが, これは絶対に読むべきです.

UEFI Specification[8]

UEFI周りの仕様を学習することができます.
UEFIはx86_64のみならず, RISC-VやArmなどでも使用可能です. そのため, 学習する価値はあると思います.

ブートローダー周りの優先度は低くてもOKです. 理論は知っておくべきですが, まだ実装に詳しく触れる必要はありません.

としていましたが, 上記2つの文献を使用することでMikanOSのブートローダー実装を理解することができるはずです.

ABI

カーネルを書くためには, アセンブリのようなCよりも低レベルなコードを書く必要があります.
そのため, どのレジスタ/スタックで引数を設定し, どのように値を返すか, というCalling Conventions(呼出規約)を知っておかなければなりません.
その為にはABI(Application Binary Interface)を知る必要があります.

System V Application Binary Interface AMD64 Architecture Processor Supplement[9]

x86_64には主にMicrosoft x64 ABIとSystem V ABIが存在しますが, System V ABIに従って実装するのがおすすめです.

カーネルとユーザー

ユーザーから見たときのカーネル理解において, 有用なのは以下の書籍です.

ハロー, Hello, World![10]

標準ライブラリとシステムコールに対して, なるほどを無限に製造できる良書籍です. 標準ライブラリを移植したくなったとき, これを読んだ経験が必ず役立ちます.

RISC-V

RISC-Vで実装したいのなら, 以下のような文献がおすすめです.

RISC-V原典[11]

RISC-Vのシンプルさと美しさを実感するような書籍です.
只でさえ薄いのに後半は命令リファレンスになっているため, 鈍器になりがちな低レイヤー関連書籍群のなかでも群を抜いて読みやすいです.

xv6: シンプルで Unix 風な 教育用オペレーティングシステム[12]

xv6のRISC-V実装を解説するpdfです.

  • 日本語
  • 無料
  • 高品質

という恐ろしいドキュメントのため, 一読することをおすすめします.

マイクロカーネル

自分はマイクロカーネルが大好きなので, おまけとして幾つかの文献を紹介します.

オペレーティングシステム 設計と実装[13]

MINIX BOOKと呼ばれているものです. モダンオペレーティングシステムと同じ著者が書いたもので, マイクロカーネルにおける理論, そして実装としてMINIXの解説を学習することができます. これも教科書として使用されてきた名著です. みんなも読もう MINIX本!

自作OSで学ぶマイクロカーネルの設計と実装[14]

日本人のnutaさんが書いた書籍ですが, A9Nを実装するうえで非常に重要だったもののひとつです. 実装というより理論を学習するためのものですが, マイクロカーネルにおけるセオリーを知るにはこれを読むのが一番速いと思います.

マイクロカーネルの設計と実装[15]

nutaさんが無料で公開しているpdfです. Reseaというマイクロカーネルをもとに, 他のマイクロカーネルと実装を比較するものですが, 実はA9Nを作成するきっかけになったのはこれの影響が大きいです.
Reseaのソースコードは読みやすく美しい実装のため,カーネルのコードリーディング用として非常におすすめです.

seL4[16]

L4の血を受け継ぐCapability-basedなマイクロカーネルで, 形式的検証が成されています.
天才が作ったカーネルで, A9Nはこれを超えることを目標にしています.
物理メモリAllocationをカーネルで一切行わないにも関わらず, Capabilityによってセキュリティを保っているという最高にCoolなカーネルです.
注意としては,

  • 一部のコードが自動生成される. そのため, コードリーディングはややしにくい.
  • 設計は美しいが, コードとしてはそこまで美しくない.

L4Re | Fiasco[17]

L4派生のうち, APIリファレンスなどが比較的しっかりしているため設計の参考になります.

ネットワーク

ネットワーク (プロトコル・スタック)実装において, カーネル//OSの観点からは次の書籍が参考になります.

BSDカーネルの設計と実装[18]

おわりに

カーネルの設計を考えるのも実装をするのも楽しいので, みんなでカーネルを書いて最強になろう! というお気持ちで書き始めた記事でしたが, これを書く時間さえも楽しかったのは予想外でした.
現在18歳なのですが, この年齢のうちにA9N on 自作CPUしたいですね.

Xフォローしてね @horizon2k38

参考文献

脚注
  1. Andrew S. Tanenbaum (2007) “モダン オペレーティング システム 原著第二版”,
    (水野忠則・太田剛・最所 圭三・福田晃・吉沢康文 訳), ピアソン・エデュケーション・ジャパン ↩︎ ↩︎

  2. 坂井 弘亮 (2010), “リンカ・ローダ実践開発テクニック”, CQ出版 ↩︎ ↩︎

  3. 内田公太 (2021) "ゼロからのOS自作入門", マイナビ ↩︎

  4. OSDev Wiki ↩︎

  5. 蒲池輝尚 (1994) "はじめて読む486", ASCII ↩︎

  6. Intel SDM ↩︎

  7. Daniel P. Bovet・Marco Cesati (2007) “詳解LINUXカーネル”,
    (杉田由美子・清水正明・高杉昌督・平松雅巳・安井隆宏 訳), O'Reilly Japan ↩︎

  8. UEFI Specification ↩︎

  9. System V Application Binary Interface AMD64 Architecture Processor Supplement ↩︎

  10. 坂井 弘亮 (2015), “ハロー"Hello,World" OSと標準ライブラリのシゴトとしくみ”, 秀和システム ↩︎

  11. David Patterson, Andrew Waterman (2018) “RISC-V原典”,
    (成田光彰 訳), 日経BP社 ↩︎

  12. xv6: シンプルで Unix 風な 教育用オペレーティングシステム ↩︎

  13. Andrew S. Tanenbaum (2007) “オペレーティングシステム 第三版”,
    (吉澤康文・木村信二・永見明久・峯博史 訳), ピアソン・エデュケーション・ジャパン ↩︎

  14. 怒田晟也 (2023) “自作OSで学ぶマイクロカーネルの設計と実装”, 秀和システム ↩︎

  15. マイクロカーネルの設計と実装 ↩︎

  16. seL4 ↩︎

  17. L4Re | Fiasco ↩︎

  18. Marshall Kirk McKusic・George V. Neville-Neil (2005) “BSDカーネルの設計と実装,
    (砂原秀樹・歌代和正 訳), ASCII ↩︎

Discussion