あえず自分でOSつくっちゃった話 があまりにわからなかったか...

55
OS があまりにわからなかったからとり あえず自分で OS つくっちゃった話 03-150508 野上和加奈

Transcript of あえず自分でOSつくっちゃった話 があまりにわからなかったか...

OSがあまりにわからなかったからとりあえず自分でOSつくっちゃった話

03-150508 野上和加奈

動機

・もう6学期だし真面目に勉強しようと思った

・真面目に授業聞いてみたけどよくわからなかった

・Amazonみてたら「OS自作」という文字列を発見

・話し聞いてもよくわからないしもはや自分で作っちゃえばいいんじゃない?

・駒場祭付近暇だしそこで、一気に作っちゃおう

0 step 本選び

・OS自作についての本はいくつかあった

・リアルタイム性など、何かに特化したものを除くと有名なものは以下の2つ

候補1:「30日でできる!OS自作入門」 小林秀実著

候補2:「12ステップで作る組み込みOS自作入門」 坂井弘亮著

0 step 本選び

候補1:「30日でできる!OS自作入門」 小林秀実著

プログラミングの基礎からはじめて、30日後にはウィンドウシス

テムを有する32bitマルチタスクOSをフルスクラッチで作り上げ

るという入門書。ビギナーでも無理なく作成できるようPCの仕組

み・アセンブラ・Cの解説から始まり、試行錯誤を繰り返しながら

アルゴリズムを学びつつ、たのしく自由な雰囲気でOSをゼロか

ら構築していくという、他に類を見ない手法による、趣味と実用

と学習を兼ね備えたOS作成の入門書。

                 

0 step 本選び

候補2:「12ステップで作る組み込みOS自作入門」 坂井弘亮

手軽に購入できるマイコンボード上で動作する独自の組込

みOSをフルスクラッチで自作する。ブートローダーも自作し

ますので、電源ONの一番最初の動作からの理解/学習

が可能です。また内容は12ステップに分かれているため、

講義や輪講、実習などでの教材利用にも向いている

0 step 本選び

・授業でやる内容に関して理解が深まるか

・駒場祭による休講、祝日(実質4日)で実装できるか

・難しすぎないか

などを基準に選定

→「12ステップで作る組み込みOS自作入門」 に決定!

はじめに

組込みOSとは?

 →ある特定の機器に搭載して制御するためのOS

 →ここではマイコンボード上で動くOSを実装

このOSでなにができるか?

 →I/Oはシリアル通信だけ

 →PCからの文字入力に応答したり、文字を出力したりする

はじめに

それだけの機能でOSといえるか?

 →OSの基本機能は資源管理

 →スレッドによるCPU時間の管理の実装

 →固定サイズのメモリ管理の実装

 →シリアル通信でI/Oの管理の実装

 →よってOSと言っても良いのではないか

はじめに

このOSには実用性がないのではないか?

 →「使う」ではなく「作る」ことが目的

 →実用性は問題ではない

はじめに

マイコンボードH8/3069Fの組み込みOSを実装

・PCとシリアルケーブルでつなぐ

・端末エミュレータでPCからマイコンを操作

・PC側でマイコンの動作の様子を見る

開発の流れ

第1部 ブート・ローダーの作成       第2部 OSの作成

1st step 開発環境の作成 7th step 割込み処理を実装する

2nd step シリアル通信 8th step スレッドを実装する

3rd step 静的変数の読み書き  9th step 優先度スケジューリング

4th step シリアル経由でファイルを転送する 10th step OSのメモリ管理

5th step ELFフォーマットの展開 11th step タスク間通信を実装する

6th step もう一度、Hello World 12th step 外部割込みを実装する

1st step 開発環境の構築

H8/3069Fネット対応マイコンLANボード(完成品)

通販コード K-01271

発売日 2006/01/23

1台 ¥3,750(税込)

→秋月電子通商で購入可

1st step 開発環境の構築

やること

・開発のための環境構築

・”Hello World”を出力するプログラムを動作させる

1st step 開発環境の構築

割込みベクタによって実行開始するアドレスを定義

 →スタートアップのstartという関数から始まるように定義

スタートアップをアセンブラで実装

 →startという関数はスタックポインタの設定を行ったあとmain()を呼び出す

メイン関数ではputs()という関数で「Hello World!」という文字列を出力

ライブラリ関数として1文字送信関数putc()とそれを複数回用いた文字列送信関数puts()を実装

1st step 開発環境の構築

その他

・ライブラリ関数のヘッダファイル

・シリアル・デバイス・ドライバ

・メモリをあつかうリンカスクリプト

なども実装した。

1st step 開発環境の構築

実行結果

2nd step シリアル通信

やること

・必要なC言語の標準ライブラリの関数の実装

・数字を表示する関数の実装

2nd step シリアル通信memset() : メモリを特定の倍てデータで埋める

memcpy() : メモリのコピー

memcmp() : メモリの比較

strlen() : 文字列の長さ

strcpy() : 文字列のコピー

strcmp() : 文字列の比較

strncpy() : 長さ指定での文字列の比較   などのおなじみのライブラリ関数を実装

2nd step シリアル通信

putxval() : 整数値を16進数で出力するライブラリ関数を実装

当然、それに伴って

ヘッダファイルの変更なども行った。

2nd step シリアル通信

実行結果

3rd step 静的変数の読み書き

やること

・静的関数の書き換えができるようにする

3rd step 静的変数の読み書き

メモリをあつかうリンカスクリプトを修正

 →いままでROMだけを扱っていたがRAMも扱えるようにメモリ領域を定義

 →各セクションをどこに配置するか定義

 →静的関数が配置されるdataセクション、bssセクションはRAMとROMの両方に配置さ

れるように定義

 →スタックの定義の追加

3rd step 静的変数の読み書き

実行結果

4th step シリアル経由でファイルを転送する

やること

・XMODEMの実装

4th step シリアル経由でファイルを転送する

XMODEMとは

→シリアル通信でファイルを送るためのプロトコル

4th step シリアル経由でファイルを転送する

XMODEMのプロトコルに従ってXMODEMを実装

ファイルの受信処理の開始などをコマンドで操作できるようにmain関数がコマンド入力を

受け付けるように変更

 →”load”で受信処理開始

 →”dump”でメモリを16進で出力

 →それ以外の入力には”unknown”とかえす

4th step シリアル経由でファイルを転送する

リンカスクリプトで受信バッファのための領域を定義

デバイスドライバにデータ受信のための関数を追加

コンソールでの1文字受信関数getc(),文字列受信関数gets()をライブラリに追加

 →マイコンボードの動作が確認できるようにエコーバックも実装している

4th step シリアル経由でファイルを転送する

実行結果

5th step ELFフォーマットの展開

やること

・OSを起動させるための「実行形式ファイル」を転送する

・それを解析して、メモリ上に展開できるようにする

 (ここではセグメント情報を表示させるとこまで)

5th step ELFフォーマットの展開

実行結果①

5th step ELFフォーマットの展開

実行結果②

6th step もう一度、Hello World

やること

・実際に実行形式ファイルを展開して「Hello World」を作成する

6th step もう一度、Hello World

ブートローダー側

5th step で表示できるようにした部分をmemcpy()によって実際に動作させるメモリ上に

コピー

main関数をロードしたプログラムに処理を渡すように変更

6th step もう一度、Hello World

OS側

基本的にはここまで書いてきたコードが使える

コンソールからの入力を受付け、echo,exitコマンドに対して処理を行うようなmain関数を

実装

OSようにリンカスクリプトのメモリ定義を書き直す

6th step もう一度、Hello World

実行結果

7th step 割込み処理を実装する

やること

・割込み処理ができるようにする

7th step 割込み処理を実装する

ブートローダー側

割込み処理の前と後におこなう処理(メモリの退避、復帰など)をアセンブラで実装

割込みベクタを変更し割込みが起こった時に実行すべきアドレスを指定

その他

・割込みベクタ関連の定義や初期化などを実装

7th step 割込み処理を実装する

OS側

シリアル受信割込みを受け付けるように、シリアルデバイスドライバに割込み機能を追加

main関数を割込みによって動作するように変更

7th step 割込み処理を実装する

実行結果

8th step スレッドを実装する

やること

・スレッド動作を実装する

・OSの持つサービスを利用するための「システム・コール」を実装する

8th step スレッドを実装する

ブートローダー側

リンカスクリプトの書き換え

 →スタックを用途別に明示的に分離

それに伴い、割込み処理やスタートアップで用途にあったスタックを使うように変更

ブートローダー側はこれで完成!

8th step スレッドを実装する

OS側

リンカスクリプトの書き換え(同様)

スレッドのディスパッチ処理を追加

スレッドの生成、終了、システムコールの呼び出しを行う関数などを実装

リンクリスト構造でスレッドを管理

8th step スレッドを実装する

実行結果

9th step 優先度スケジューリング

やること

・スレッドに優先度を導入する

・システム・コールを追加する

・スレッドの「スリープ」状態を実装する

9th step 優先度スケジューリング

優先度を追加

レディ−キューの配列を優先順位の高い順に検索し、動作可能なスレッドを探す

 →優先順位の高い方から実行

スレッドの切り替えを行う関数や、スレッドをスリープ状態にする/起こす関数、優先度を変

更する関数、スレッドIDを取得する関数を実装

9th step 優先度スケジューリング

実行結果

10th step OSのメモリ管理

やること

・メモリ管理ができるようにするために、「malloc」「free」などを実装する

10th step OSのメモリ管理

あらかじめ16バイト×8個、32バイト×8個、64バイト×4個の領域を用意する

それらをリンクリストでつなぐ

メモリが要求されたら収まる最小サイズの領域をリンクリストから切り離して与える

開放されたらまたリンクリストに繋ぎ直す

10th step OSのメモリ管理

実験結果

11th step タスク間通信を実装する

やること

・スレッド間で情報をやりとりするためのタスク間通信の機能を実装する

11th step タスク間通信を実装する

メッセージをいくつかのボックスにわけレディーキューでつないで送信する

11th step タスク間通信を実装する

実行結果

12th step 外部割込みを実装する

やること

・1文字受信割込みを受け付ける「割込み処理」を実装する

・コマンド応答スレッドを作成する

12th step 外部割込みを実装する

やること

割込みハンドラからシステムコールを呼び出せるようにトラップ命令を発行せずにシステ

ムコールの処理を関数呼び出しするサービス関数を実装

12th step 外部割込みを実装する

実行結果