宮水の日記

宮水の日記

主に書評や資格取得について記事を書いています。

ゼロからのOS自作入門 〜環境構築からブートローダの作成まで〜

ゼロからのOS自作入門を購入しました!このブログでは、環境構築からブートローダの作成まで(本書の3章まで)を通して自分なりに分かったことを日記として投稿します。(調べながら書いたので、である調とですます調が混ざってますが、大目にみてください。)

ゼロからのOS自作入門

ゼロからのOS自作入門

f:id:kattyan53:20210430134705p:plain

読んだ理由

この本をTwitterのタイムラインで見かけて、元々〇〇自作にとても興味があり、面白そうだと思ったので購入しました。普段当たり前のようにお世話になっているOSですが、全く知らないのでこの本を通して学んでいきたいと思いました。

対象読者

本書によると、「簡単なプログラムを書いたことがある人」とのこと。

この本で学べること

  • CやC++を使って"全部自分で"OSを自作する

私のスペック

  • 普段はよくRubyを書いており、ソフトウェアエンジニアをしています。CやC++は今回初めてです。
  • よく使っているOSはmacOSです。
  • Vim、Git/Githubは調べながら使えます。
  • 基本情報技術者に2年くらい前にギリギリで合格しました。
  • 自作は全く初めてです。(mountコマンドの意味さえ知りませんでした。)

3章までやった感想としては、「とりあえず動かせるので楽しいけど、前提知識がなさすぎて解説が80%くらい理解できない」という感じです。

開発環境の構築

本書によると、2012年以降に発売されたパソコンを使うことが推奨されており、UbuntuWindowsで仮想環境を作ってLinuxが使えるようになるWSL (Windows Subsystem for Linux) 、QEMU(仮想環境)を使うやり方が紹介されています。

私は最初ベストな環境構築が分からなくて、1週間くらいハマりました。本当はMacで開発しようと思っていたのですが自分がよく分からないものは入れたくなかったので、フリマアプリで壊れてもいいパソコンを買って、本書で紹介されているLinux環境を作ることにしました。パソコンのスペックとUSBは以下です。

Lenovo Thinkpad X121e

  • 8500円
  • CPU:Core i3-2357M 1.3GHz
  • メモリ:DDR3 4GB
  • HDD:320GB
  • wifi繋げられる
  • USB挿せる
  • OS:Windows 10 Home 64bit

② USB

  • 数百円
  • 8GB
  • 規格はUSB3.0(私の買ったLenovo Thinkpad X121e はUSB2.0しか使えないので、3.0のUSBを買っても2.0の速さしか出ないらしいです。よくわかってませんが。)

Windows10を完全に削除してUbuntuをインストールして開発を進めました。以下の記事が参考になりました。
yoshinorin.net

BIOSの設定は、「ThinkPadロゴが出たらF1を長押し」でいけました。私が購入した機種ではセキュアブートは設定されていなかった(設定できない?)ようで、BIOSのStartupのBootの設定から、起動時の設定でUSBの優先度をあげると、USBからでも無事起動できました☺️

試行錯誤した結果、最終的に開発環境と動作確認用端末が一緒になってしまったので、今はQEMUを使って開発を進めています。

1章 PCの仕組みとハローワールド

この章でやること

バイナリファイルを書いてUSBに配置して起動させます。

ブートローダ

ブートローダとは、OSをメインメモリに読み込み、起動させるプログラムのこと。

BOOTX64.EFIファイル

実行可能ファイルといって、CPUが実行可能な機械語を含んだファイルのこと。

CPU

デジタル回路で構成されており、電圧の高低、すなわち2進数を扱う。今回バイナリファイルを16進数で書いたのは、16進数の方が2進数に変換しやすいから。

UEFI

オペレーティングシステム(OS)とプラットフォームファームウェアとの間のソフトウェアインタフェースを定義する仕様のこと。OSを起動するために必要な機能を提供するブートサービスと、OS起動前、起動後どちらでも使える機能を提供するランタイムサービスから構成されている。
Unified Extensible Firmware Interface - Wikipedia(ja)

UEFI BIOS

UEFIという標準仕様に従って作られたBIOSのこと。本書でやったファイルシステムFATでフォーマットされた起動ディスクの \EFI\BOOT\ ディレクトリ下に配置されたファイルで起動するというのは、UEFIの仕様のひとつ。

mount

脳死でumountとかmountとかコマンドを打っていました。
f:id:kattyan53:20210430135226p:plain

どうして普通にUSBにファイルを置くだけでは起動しないのか分からなかったので、teratailで質問してコマンドの丁寧な解説までいただきました😢 USBメモリのルートディレクトリ下にただコピーしただけでは、PCのUEFIからOSを起動することはできないそうです。UEFIの仕様に従ってBIOSを起動するために、USBをFATでフォーマットし、mountして起動ディスクの \EFI\BOOT\ ディレクトリ下にファイルを配置したということでした。(難)
Linux - デバイスファイルにアクセスしてコピーしないと起動しないのはどうしてですか|teratail

mountの説明は以下の通りです。

「mount」は、HDDやUSBメモリ、DVD-ROMなどのフォーマット済みの領域(ファイルシステム)を指定したディレクトリ(マウントポイント)と一時的に結び付けてアクセスできるようにするコマンドです
引用元:
【 mount 】コマンド――ファイルシステムをマウントする:Linux基本コマンドTips(183) - @IT

2章 EDK Ⅱ 入門とメモリマップ

この章でやること
  • EDK Ⅱという開発ツールを使ってみる。C言語で書かれたファイルをBuildして、上記で書いたバイナリファイルと同じものを作り、これをUSBメモリからメインメモリに読み込ませます。
  • UEFIの機能を使ってOSにメモリマップを渡すための準備として、メモリマップを取得したりファイルに一時保存してみたりします。

EDK Ⅱ

UEFI BIOS自体の開発、UEFI BIOS上で動くアプリケーションの開発などにも使える開発キット。

メインメモリ

メインメモリとは、プログラムやデータを一時的に蓄えておくための装置で、CPUの命令で直接アクセスできる装置のことです。

メインメモリとは何? Weblio辞書

メモリマップ

メインメモリのどの部分がどんな用途で使われているか載っている地図のことです。

ポインタ

ポインタとは、変数のアドレスを記憶する変数のことです。

納得C言語 [第13回]ポインタ - ほぷしぃ

構造体

C言語では、複数のデータ型を複数格納することができる箱を作ることができます。

納得C言語 [第14回]構造体 - ほぷしぃ

3章 画面表示の練習とブートローダ

この章でやること
  • main.cppを書く→clang++コマンドでソースコードコンパイルし、オブジェクトファイルmain.oを作成→ld.lldによってオブジェクトファイルから実行可能ファイル(kernel.elfファイル)を作成する。→edk2を使ってブートローダをbuildする→カーネルが起動する

Main.cファイルがブートローダで、main.cppがカーネルなんですね☺️



レジスタ

CPUに内蔵された記憶領域のこと。容量が小さく読み書きが速い。

カーネル

カーネル(英: kernel)は、階層型に設計されたオペレーティングシステム (OS) の中核となる部分である。

カーネル - Wikipedia

オブジェクトファイル

ソースコードコンパイルした結果の機械御命令を含んだファイル。

まとめ

今回は、3章まで進めました。正直なところ、CとC++で書かれたファイルはあんまりちゃんと読めていません。 しかしながら、何をやっているか抽象的に理解しつつ、書き写して実行するだけでも楽しいです👍 これからも少しずつ進めていこうと思います。

ゼロからのOS自作入門

ゼロからのOS自作入門

ここまでお読みいただきありがとうございました!