【2024年最新】0から作る!高校生による全ての人のためのOS開発講座#0 Hello World編
対象と動機について
どうもまだ高校生です。この記事は小学生から大人で趣味としてプログラミングを行う人まで、幅広い世代に向けて執筆されたものです。なぜ小学生も対象に含まれているのか。それはひとえに、私が小学生の頃にOSを作るのに挫折したからであります。私の時よりもデジタルに強い子供たちは多くなってきていますので、需要はあると踏んでいます。ただ詳しく説明しているから君たちは少し難しいと思うかもしれない。ノートとペンを持って、メモしながら進めてみよう!
また、AIの時代を生きる若者をはじめとした人々に、コンピュータの古き良き時代の息吹を感じていただきたいと思ったのが動機にあります。
私は上級者じゃ!という方は、私が今後投稿する記事を読んでいただきたいと思います。フォローして待っていてくださると嬉しいです。
内容
今回はOSの基本的な機能、カーネル(kernel:核)を作ります。そして皆さんがいつも疑問に思っていた「Hello World」を表示するための長い旅にいざないます。
当然のことながらOSはすでに完成はしているのですが、スペックの低いパソコンでも作れるように改めて作っていきますので、一緒に学んでいく構成になっています!ただのメモとか、備忘録ではありませんよ。「講座」ですからね。
そして、あなた自身のオリジナルOSが作れます!最後まで頑張りましょう!
また、C言語よりももっと機械語に近い、アセンブリ言語という低水準言語を扱いますが、ちゃんと分かりやすく解説しますので楽しみにしていてくださいね!
分からない用語ができるだけないように解説を書きますのでご安心ください。なんとなく知っているという方も学びになると思います。また、出版などのお声がけをいただけた場合、本記事で書ききれなかった内容も解説したいなと考えております。なのでフォローをしてお待ちいただきたく思います。
小中学生の方は自由研究としてやっていただいても構いません(内容を自分なりに要約してみよう!)。その他の方も引用していただい構いません。ただ、クレジット表記をしていただきます。「まだ高校生」だけで結構です。では早速本題に移りましょう!
※本記事は有料記事となります。小中学生でも貯金から出せる、1000円という値段設定にさせていただきました。本当は大学生が情報工学などの授業で学ぶものですので破格ですよ!しかも分かりやすいですからね!
開発環境について
CPU - MacでもWindowsでも!
今回OSの開発をする上で、x86_64というCPUアーキテクチャ(CPUの種類のこと)が要求されるのですが、実は今の時代、仮想環境を用いることでARM,x86を問わずに開発することができます。筆者のCPUはApple Silicon M2 ですが、問題なく開発ができています。
また、もともとintelのパソコンだよって方も仮想環境を使うことをお勧めいたします。それは、色々と開発するためのツールをパソコンにインストールしてディスクの中が多少汚れるためです。よく分からないファイルがこの先ずっとどこかで潜んでいるのも嫌でしょう?筆者はおすすめします。その前提で話を進めさせていただきます。
また難しい用語が出てきましたね。
x86は複雑な処理を簡潔な命令で実行できるCPUで、
ARMはエネルギー効率を重視したCPUのことです。
もっと知りたいという方はこちらを読むことをおすすめ致します。興味深い歴史と種類を知れますよ。https://www.wakuwakubank.com/posts/809-it-cpu-x86-x64-arm/ https://www.redhat.com/ja/topics/linux/ARM-vs-x86
ディスク容量
仮想環境と、その他ツールやファイルサイズを考慮して20GBあれば十分かと思います。一般に、仮想ソフトで事前に20~30GBほどを"予約"するのですが、実際の利用容量は、筆者の場合7GB(Q4OS),14GB(kali)ですので、OSの容量に合わせてお好みにアレンジしてみてはいかがでしょうか。軽量のOSの場合であれば15GBで大丈夫かと思います
※Q4OS,Kaliというのは、のちに説明するLinuxOSのうちの2つです。
メモリ容量
メモリは軽量のOSなら4GBでもいけます。8GBあると安心です。16GB以上なら十分でしょう。
仮想環境①Unix,Linuxとは
今回の開発ではGNU/LinuxというUnix系のOSを用います(この後ダウンロードするもので、今のパソコンのOSとは関係ありませんよ!)。Unixとは1969年と、とても古くからあるOSで、そこから派生してLinuxやMacOSなどが作られました。しかしそのUnixは完全無償で使うことができません。そこでGNU(GNU is Not Unix!という再帰的な略称)というUnixに限りなく近い、フリーなOSや、カスタマイズ性の高いLinuxなどが出てきたのです。そして、そのLinuxの中でも無償で使えるのが今回触れる、Debian系のkali linux, Ubuntuや、Q4OSといったその他無償のOSです。
※UbuntuはDebianプロジェクトという、無償で公開されているOSの代表的なOSです。また、RedHat,Slackware,Arch系は有償、非自動化、多機能による初心者殺しなどの理由から紹介はいたしません。
仮想環境②仮想化ソフト
Macの方はUTM(https://mac.getutm.app)という仮想化ソフトをお勧めいたします。(とてもシンプルで使いやすい!)
ARM(M1,M2,M3)の方はエミュレート(ARM→x86のCPU間の翻訳)という形でこのソフトを使います。これでx86のLinuxを動かすことになります。
Intelの方は仮想化(CPUの規格が同じなMacOS上でLinuxを動かす)を行います。
Windowsの方は、WSLを使えば仮想ソフトを挟まずにGNU/LinuxのCUIを実現できるのですが、ホスト側に影響が及ぶのでやはり同じく仮想ソフトをおすすめます。実際私もかつてプログラムを動かしたい時に動かせず、その理由が昔設定したWSLで、コントロールパネルから設定し直す必要が出てきたりもしました。
そこでおすすめするのがVirtualBoxです。そこまで難しくないので使ってみてください。Intelの方はそれで仮想化ができます。
ARMの人はすいません。WSLかQEMU(Quick EMUlator)を使うことになります。ここでの説明は省略させていただきますが、qemuをおすすめしたいです。中級者はどちらでも良いと思いますが。
VirtualBox: https://www.virtualbox.org/wiki/Downloads
Linuxどれを選ぶ?
そしてx86のLinux iosファイルで仮想環境を構築しましょう。
(UTMならhttps://mac.getutm.app/gallery/ubuntu-14-04 からx86のUbuntuをダウンロードできます。)
私は今回、Q4OSという軽量なLinuxディストリビューションを使っていきます。私はBasicを選びました。
(https://www.youtube.com/watch?v=0f1AxIswg8s)
もちろん、好きなDebianベースのLinuxディストリビューションで良いです。ただ、初心者で、ディスク容量もあってパソコンの性能もある程度ある方ならkali linux,Ubuntuなどの有名なLinuxをおすすめします。はじめはその方が情報や、必要なものが揃っているので躓かなくて済みます…!
kali linux:https://www.kali.org/get-kali/#kali-installer-images Ubuntu:https://ubuntu.com/download/desktop
必ずx86のisoかどうか、仮想化なのかエミュレートなのかを確認してください
Linuxのインストールと諸注意
さて、早速Linuxをインストールしてみましょう。ここではUTMのみ解説しますが、VirtulaBoxでもやることは同じです。ただ!先ほども言ったように仮想化なのかエミュレートなのかを確認してくださいね。
私はM2なのでUTMでエミュレートを選択し、先ほどダウンロードしたisoファイルを選択します。仮想環境のためのメモリ、CPUのコア数は、実機の半分ほどを選びましょう。8GBなら4GB、8コアなら4コアに設定しましょう。匙加減はお任せします。
ここで注意点があります。一つは言語設定です。Ubuntuなどの比較的整備されているOSなら問題ないかと思いますが、antiXやQ4OSなどでは、インストール時の言語設定を英語にしないとインストールができないことがあります。
また、今後コマンドでフォルダ指定するときもいちいち日本語に対応させて、コマンドを打つたびに日本語と英語を切り替えるハメになります。要注意です。
二つ目はOSのDVD/USBの抜き忘れです。仮想環境といえど、パソコンにOSをインストールするときは仮想的にもDVDなどが入っています。インストールが終わった段階で、それらをEject(取り出し)しましょう。このタイミングを間違えると、せっかくインストールしたのにまたインストールするという、インストール地獄にいきます。
この動画を参考に、CD/DVDの抜くタイミングを知ってくださいね。
途中で間違えていますが、重要なのは4:00以降の動き方です。
virtIO,VGAとは何か
※ここはおそらくVirtualBoxの方は関係ありません。飛ばしていただいて構いませんが、教養のために読みたい方はぜひ読んでみてください。
また、ディスプレイの設定を変更するのを忘れずに。なぜかというと、OSによっては画面を表示できないことがあるからです。ずっと待ってもインストール画面が出ない、若しくはインストールボタンを押した後から何も進まないという場合は、この設定を変えれば動かすことがでます。
下の写真の下半分には、virtio(読:ヴァーティオ)という文字が並んでいます。これは2008年以降のOSから標準化された、仮想マシンとホストマシン間の高速なデータ転送を可能にするインターフェイスです。virtioのio、IOフレームワークというのは、入出力(In,Out)を処理するためのライブラリの集合体のことです。
上記のような状況の際は、多くの場合、virtio-ramfb-gl(GPU Supported)を選択すると解決します。ramfbとは、RAM(Random Access Memory)+FB(FrameBuffer)に分けられ、ピクセルデータのためのメモリ領域という意味になります。このramfbは、ゲストOSが実際のGPUドライバをロードするまで、ファームウェア(ハードウェアの制御や設定、構成を行うプログラム)によって構成され、ブートフレームバッファとして使用されます。ホストのGPUなどに依存せずにゲスト側のピクセルデータを一時保存し、それをホスト側でキャプチャする仕組みです。※Buffer=緩衝材= 一時的な保存領域
写真の上にはVGA(Video Graphics Array)という文字がほぼ全てに含まれています。これは1987と古くからあるアダプタですので、どんなOSにも対応しています。ビデオ出力で困ったらこれを選択しておけば間違いありません。HDMIの下位互換と考えていただければと思います。その中で私が選んだのはSpice(Simple Protocol for Independent Computing Environments) QXL(QEMUのビデオデバイス) GPU を選んでいます。これにより、仮想GPUを設置して高パフォーマンスな出力を実現できます。また、qxl-vgaは仮想環境に適したVGAの上位互換的アダプタです。
Linuxを学ぶ
環境整備・コマンド編
インストールができたら早速いじってみましょう。Debianのコマンドを使っていきますよ。
$ uname -a
とコマンドを打ってx86であることを確認してください。これでarmだったら、isoファイルを間違えたことになります。unameコマンドはLinuxで使う、情報を得るためのコマンドです。詳しくはこちら:https://eng-entrance.com/linux-command-uname
そしたら
$ sudo apt update
というコマンドを実行してください。パスワードを求められたら設定したパスワードを入力してください。このsudoはroot(根っこ)権限を使えるコマンドです。aptはaptitude(才能,能力)の略称で、Debian系のLinuxにおいてソフトウェアのインストール、アンインストールの管理ができるコマンドです。もし、今後aptを使ってエラーが出たらapt-getと書いてみてください。直ることがあります。これは難しい話で、AWSの記事を読んでもあまり分かりません。しかし直るので試してみて損はないでしょう。aptは今後使っていくので覚えておきましょう。
次に、
$ man as
とコマンドを打ちましょう。manコマンドはマニュアル(manual)のmanです。asはGNUのアセンブラ、GAS(GNU Assembler)を指します。アセンブラについては後で説明しますね。ズラーっと書いてあるマニュアルが表示されたら大丈夫です。これでしっかりと、x86のLinuxとアセンブラを準備できたことになります。おめでとうございます!qで閉じれます。
その次はGCC(GNU Compiler Collection)です。これはGNUプロジェクトが開発を行なっていて、今やほぼ全てのUnix系OSにも浸透している、さまざまな言語のコンパイラ(プログラム→機械語への一括翻訳を行うもの)を集めたものです。
このGCCのバージョンが6.4以上でないといけません。(エラーが出てしまうので)そこで、
$ gcc -v
と入力して確認してみてください。もしバージョンが低いなら更新してください。(https://qiita.com/keisukeYamagishi/items/9f345b6636cafd7d83bb)
筆者の軽量Linuxには標準で入っていませんでしたので、
$sudo apt install gcc
でインストールしました。おそらく後のことを考えると、gccが含まれる
$ sudo apt install build-essential
の方が良いかもしれませんが、解説が多くなってしまうので(笑)、gccだけをインストールしていきます。
xorriso(読み:チョリソーorエクソリソ、諸説あり)は、ISO 9660(標準化されたファイルシステム)イメージを作成して操作し、CD-ROM または DVD-ROM を書き込むプログラムです。少し難しいですが、ISOイメージの作成、変更などを行うことができるんだと覚えてください。※詳しくはこちら:https://ja.wikipedia.org/wiki/ISO_9660
これも、
$ man xorriso
でマニュアルが出るか、確認してみましょう。
ない場合は、
$ sudo apt install xorriso
でインストールしましょう。
grub-mkrescueですが、これはGRUB(GRand Unified Bootloader:壮大な、統合されたブートローダー)というブートローダを使ってブート可能なISOイメージを作成するための便利なツールです。この"mk"は作るという英語のMake、rescueはそのままレスキューです。よって、"救いを作る"。そうです。システムのトラブルシューティングや修復に役立つものなんですね。
これも
$ man grub-mkrescue
とコマンドを入力してみましょう。make a GRUB rescue image と出てきましたね。
基本は標準で入っているはずですが、ない場合は、
sudo apt install grub-pc-bin grub-common
を実行してみてください。それでも上手くいかなかったらこのサイトを参考にしてみてください。https://gcore.com/learning/how-to-install-grub-bootloader-in-linux/
最後に、QEMUをインストールします。先ほども出てきましたね。メモしてないと忘れてきますからね?ちゃんと書いてますか?笑
入っているかどうかは、
$ qemu-system-x86_64 --version
で分かります。インストールされていない場合は、
$ sudo apt install qemu-system
でインストールできます。
コマンドの深掘り①-アセンブラ・AT&T,Intel構文とは
さて、一気に難しい話が出てきましたよね。途中で出てきたGCC,GASってなんだろうって思いますよね。
GCCはコンパイラの集まり、GASはアセンブラです。アセンブラとコンパイラとの大きな違いは高級言語を翻訳するのか低級言語を翻訳するのか、です。機械語に近い低級言語であるアセンブリ言語を翻訳するのが、アセンブラということになります。
どうやって翻訳しているのか、16進数との関係を見てみたいという方はこちらを開いて実行してみてください。モチベーションが上がるでしょう?中には落ち込む方もいるかもしれませんが。(笑)http://schweigi.github.io/assembler-simulator/
とにかく、これらのGNUのツールにより、プログラムをGCCでアセンブリコードに変換し、GASでアセンブルするという連携が可能になります。
ちなみに、インタプリタというのはコンパイラと違い、1行ずつ機械語に翻訳します。例えばRuby,Pythonなどがあります。覚えておきましょう。
また、アセンブラにも種類があって、一般的なもので言えば
GAS (GNU Assembler)
NASM (Netwide Assembler)
MASM (Microsoft Macro Assembler)
TASM (Turbo Assembler) などが挙げられます。
実はこの中で、GASが仲間外れなんです。なぜなら最後にMが付かないから~! はい、嘘です(笑)
本当は、GASだけがAT&Tという、違う構文で書かれ、x86、x86-64以外にもarm,PowerPC(2005年までAppleが使っていたアーキテクチャ)などにも対応しているという点で仲間外れです。その他はintel構文を用います。また、後者2人は主にWindows系で使われるのですが、前者2人はそれぞれUnix/Linux , クロスプラットフォームとなっています。そのため、Linuxの分野でよく聞くのはGASとNASMですね。自作OS#1以降からNASMにも触れたいと思います。
では構文(ITの世界ではSyntaxと呼びます。)について軽く触れます。あとでGASを実際に書きますので、ここでは簡単な雰囲気をお教えします。
まず事前知識です。
mnemonic: 命令を表すキーワード(ニーモニック)
dest: 命令の結果が格納される目的地(destination)
src: 操作の元となるソースデータ(source)
これが大事になってきます。ちなみに、このような演算で使うdest,srcをオペランドと呼びます。
さて、これをそれぞれの構文では、
AT&T構文:mnemonic src, dest
Intel構文 :mnemonic dest, src
の順番で書きます。
また、AT&T構文ではレジスタに%が接頭辞としてつきます。
レジスタというのはCPU内部にある高速で小容量の記憶装置のことです。
※のちに解説いたしますので、今は雰囲気だけでいいですからね。
例として即値「1」をレジスタに移動させる時は
AT&T構文:movl $1, %eax
Intel構文 :mov eax, 1
となります。雰囲気、分かりましたか?
実は、ディレクティブ(命令、指示を意味する。動詞はディレクト。よくTVでディレクターと聞くと思いますがそれです。)という、「.」から始まるコンパイラに出す指令で、
.intel_syntax noprefix
と指令を出すとGASでもIntel記法が使えます。
みなさんの中には今後、私の#1,#2と、OS開発をして、NASMなども使おうと考えている方が多いかと思いますが、説明が多くなってしまうので、今回はAT&T構文を用いて開発を行いたいと思います。
コマンドの深掘り②-ブートローダーとは
grub-mkrescueのところで頻繁に出てきたブートローダー。これを解説していきますね。ブートローダーというのはビックバンで言うところのインフレーションですね。といっても分かりにくいかもしれないんですが、パソコンの電源を入れてから一番初めに
BIOS(Basic Input/Output System)/UEFI(Unified Extensible Firmware Interface)が起動し、彼らがブートローダーを呼び出し、呼び出されたブートローダーがOSを起動します。
このようなプロセスがあるんですね。
また、この呼び出す(起動する)ことをブートと言います。
OS開発開始!
いよいよ開発に取り掛かっていきます。まずは、ブートローダに私たちが作るOSを認識してもらうためのファイルを作っていきましょう。
ここから先は
この記事が気に入ったらチップで応援してみませんか?