Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

【2000行弱!】x86用自作カーネルの紹介

4,484 views

Published on

以下の勉強会の発表スライドです。

大人の放課後シリーズ#12:『【2000行弱!】x86用自作カーネルの紹介」』 - connpass
http://otona-after-5.connpass.com/event/27126/

Published in: Software

【2000行弱!】x86用自作カーネルの紹介

  1. 1. 【2000行弱!】x86用自作カーネルの紹介 荒川 祐真 2016/04/08
  2. 2. 2016/04/08 荒川 祐真 2 自己紹介 ● 名前: 荒川 祐真  →  大神 祐真 ● 仕事: 組み込み系のプログラマ ● 趣味: アーケードゲーム(古いシューティング系)、    OS自作(OS5) ● 最近よく使う言語(よく使うものから順に) – C言語、シェルスクリプト(言語?)、アセンブラ(x86)
  3. 3. 2016/04/08 荒川 祐真 3 自己紹介 ● 名前: 荒川 祐真  →  大神 祐真 ● 仕事: 組み込み系のプログラマ ● 趣味: アーケードゲーム(古いシューティング系)、    OS自作(OS5) ● 最近よく使う言語(よく使うものから順に) – C言語、シェルスクリプト(言語?)、アセンブラ(x86) 本日の勉強会で 紹介
  4. 4. 2016/04/08 荒川 祐真 4 今日お話する内容 1.はじめに 2.OS5の概観 3.カーネル 4.おわりに
  5. 5. 2016/04/08 荒川 祐真 5 今日お話する内容 1.はじめに 2.OS5の概観 3.カーネル 4.おわりに 時間管理、タスク管理、 メモリ管理、ファイルシステム、 システムコール 各機能が どのように実装されてきたかを 見ていきます
  6. 6. 2016/04/08 荒川 祐真 6 今日お話する内容 1.はじめに 2.OS5の概観 3.カーネル 4.おわりに
  7. 7. 2016/04/08 荒川 祐真 7 OS5とは ● フルスクラッチ – OSについて理解したことの確認
  8. 8. 2016/04/08 荒川 祐真 8 OS5とは ● フルスクラッチ – OSについて理解したことの確認 良くも悪くも、 オリジナルなOS
  9. 9. 2016/04/08 荒川 祐真 9 OS5とは ● フルスクラッチ – OSについて理解したことの確認 ● まずはシンプルに – OS5の各機能(後述)は、 「そのとき必要な最小限」で実装 良くも悪くも、 オリジナルなOS
  10. 10. 2016/04/08 荒川 祐真 10 今日お話する内容 1.はじめに 2.OS5の概観 3.カーネル 4.おわりに
  11. 11. 2016/04/08 荒川 祐真 11 まず、OS5を動かしてみる shellで使えるコマンド例 【文字列表示】  echo hello 【メモリread/write】  readl 20000f00  writel beefcafe 20000f00  readl 20000f00 【I/O read/write】  ioreadb 21 # PICのIMR  iowriteb 0 21  ioreadb 21 【アプリ起動】  uptime
  12. 12. 2016/04/08 荒川 祐真 12 OS5でできること ● OS5はQEMU上で動作 ● MakeとGCCがあれば、 x86(32bit)マシン上でビルド可能 – x86(64bit)環境用には、 ビルド環境をQEMUイメージで公開中 OS5に関する情報は以下にまとめています http://funlinux.org/os5/
  13. 13. 2016/04/08 荒川 祐真 13 コード行数の推移 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数
  14. 14. 2016/04/08 荒川 祐真 14 コード行数の推移 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数 ブートローダー・カーネル・アプリ の総コード行数
  15. 15. 2016/04/08 荒川 祐真 15 コード行数の推移 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数 ブートローダー : 253行 カーネル : 1966行 アプリケーション: 437行
  16. 16. 2016/04/08 荒川 祐真 16 コード行数の推移 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数 ブートローダー : 253行 カーネル : 1966行 アプリケーション: 437行
  17. 17. 2016/04/08 荒川 祐真 17 OS5カーネルのアーキテクチャ カーネル 時間 管理 ファイルシステム システムコール デバイスドライバ アプリ shell uptime コンソール CPU メモリ KBC CRTCPIT :機能の呼び出し関係 タスク管理 スケジューラ タスクローダ メモリ管理 ページング メモリアロケータ ソ フ ト ハ ー ド
  18. 18. 2016/04/08 荒川 祐真 18 ブートローダーの概要 今回の主題はカーネルだが、 カーネルが起動するまでの流れとして ブートローダーを簡単に紹介
  19. 19. 2016/04/08 荒川 祐真 19 ブートローダーの概要 PC 電源 ON
  20. 20. 2016/04/08 荒川 祐真 20 ブートローダーの概要 PC 電源 ON BIOS
  21. 21. 2016/04/08 荒川 祐真 21 ブートローダーの概要 PC 電源 ON BIOS ● Basic Input/Output System ● 起動デバイスのMBR(Master Boot Record、先頭512バイト) をRAMにロードし、CPUに実行させる
  22. 22. 2016/04/08 荒川 祐真 22 ブートローダーの概要 PC 電源 ON BIOS ブート ローダー ● 512バイトに収まっており、MBR自体に相当 ● 以下を行う 1. モニターの画面モード設定 2. カーネルとアプリのバイナリをRAMへロード 3. CPUモードを16ビットから32ビットへ移行 4. RAMへロードしたカーネルを実行 ※ 1と2はBIOSの機能を利用する
  23. 23. 2016/04/08 荒川 祐真 23 今日お話する内容 1.はじめに 2.OS5の概観 3.カーネル 4.おわりに
  24. 24. 2016/04/08 荒川 祐真 24 コード行数の推移 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数
  25. 25. 2016/04/08 荒川 祐真 25 コード行数の推移 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数 【主な追加機能】 ● ブートローダー ● アプリ(shell) ● デバイスドライバ(コンソール)
  26. 26. 2016/04/08 荒川 祐真 26 コード行数の推移 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数 【主な追加機能】 ● ブートローダー ● アプリ(shell) ● デバイスドライバ(コンソール)
  27. 27. 2016/04/08 荒川 祐真 27 OS5カーネルのアーキテクチャ デバイスドライバ shell コンソール CPU メモリ KBC CRTCPIT :機能の呼び出し関係 ソ フ ト ハ ー ド
  28. 28. 2016/04/08 荒川 祐真 28 デバイスドライバとは ● ハードウェアを抽象化して、 利用しやすくする ● 現状のOS5カーネルでは、 「KBC(キーボードコントローラ)」と 「CRTC(CRTコントローラ)」を 「コンソール」として抽象化している デバイスドライバ コンソール KBC CRTC
  29. 29. 2016/04/08 荒川 祐真 29 使用するハードウェアについて ● KBC(i8042) ● CRTC(MC6845) Motorola 6845 - Wikipedia, the free encyclopedia https://en.wikipedia.org/wiki/Motorola_6845 IC collections: http://www.itofamily.com/ito/collections/ ● i8253,i8254: http://www.itofamily.com/ito/collections/peripherals/i8253-54/ Arcade Artwork: http://arcadeartwork.org/ ● i8042: http://arcadeartwork.org/picture.php?/94635/category/19 「何を制御するのか」を見てみる (今、このようなICが実装されているわけでは無いですが) 他にも以下のウェブサイトなどで、 制御するICの姿を見てみると面白いです
  30. 30. 2016/04/08 荒川 祐真 30 KBC i8042について ● キーボードやマウスを管理するための ワンチップ・マイコン ● キーボードやマウスにもワンチップ・マイコン が搭載されており、それらと相互に通信する
  31. 31. 2016/04/08 荒川 祐真 31 制御用ICの使い方 ● in/out 命令を使用 ● 書式 – in ICの読み出すレジスタのアドレス, CPUの汎用レジスタ名 – out CPUの汎用レジスタ名, ICの書き込むレジスタのアドレス
  32. 32. 2016/04/08 荒川 祐真 32 KBC(i8042)の使い方 レジスタ一覧 KBC/Intel 8042 - OS Project Wiki http://www.wiki.os-project.jp/?KBC%2FIntel%208042 アセンブラのコード例 <ステータスレジスタの読み出し> in $0x0064, %al <データレジスタの読み出し> in $0x0060, %al I/Oポート R/W 内容 0x0060 R/W データレジスタ 0x0064 R ステータス・レジスタ コマンドレジスタW
  33. 33. 2016/04/08 荒川 祐真 33 CRTC MC6845について MC6845の主な機能 ● 最大256x64キャラクター ● 1文字のドット構成設定可 ● カーソル制御(形状変更、ブリンク) ● ページング、スクロール機能 CRTC (LSI) - Wikipedia https://ja.wikipedia.org/wiki/CRTC_(LSI) Motorola 6845 - Wikipedia, the free encyclopedia https://en.wikipedia.org/wiki/Motorola_6845
  34. 34. 2016/04/08 荒川 祐真 34 CRTC MC6845について MC6845の主な機能 ● 最大256x64キャラクター ● 1文字のドット構成設定可 ● カーソル制御(形状変更、ブリンク) ● ページング、スクロール機能 CRTC (LSI) - Wikipedia https://ja.wikipedia.org/wiki/CRTC_(LSI) Motorola 6845 - Wikipedia, the free encyclopedia https://en.wikipedia.org/wiki/Motorola_6845 テキストモードの画面における、 ● カーソル制御 ● 画面スクロール ● フォントデータ などを備えている便利なIC
  35. 35. 2016/04/08 荒川 祐真 35 CRTC(MC6845)の使い方 1. ブートローダーで画面モードを設定 ➔ BIOSの機能を活用 2. カーネル起動後はVRAM領域への  データ書き込みで画面描画される ➔ VRAM領域: 0x000B 8000 〜 0x000B FFFF
  36. 36. 2016/04/08 荒川 祐真 36 関連するソースコード ● os5/kernel/console_io.c ● os5/kernel/include/console_io.h
  37. 37. 2016/04/08 荒川 祐真 37 コード行数の推移 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数 【主な追加機能】 ● 時間管理 ● タスク管理 (スケジューラによる マルチタスク) ● アプリ(uptime)
  38. 38. 2016/04/08 荒川 祐真 38 コード行数の推移 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数 【主な追加機能】 ● 時間管理 ● タスク管理 (スケジューラによる マルチタスク) ● アプリ(uptime)
  39. 39. 2016/04/08 荒川 祐真 39 OS5カーネルのアーキテクチャ 時間 管理 デバイスドライバ shell コンソール CPU メモリ KBC CRTCPIT :機能の呼び出し関係 ソ フ ト ハ ー ド
  40. 40. 2016/04/08 荒川 祐真 40 時間管理について ● 役割 – 時間という単位の生成・管理・提供 ● やっていること – タイマー割り込み毎(10ms)に グローバルなカウンタ用変数をインクリメント ● 使用するハードウェア – PIT(Programmable Interval Timer) PIT
  41. 41. 2016/04/08 荒川 祐真 41 使用するハードウェアについて PIT(i8253あるいはi8254) ● 16bit長のカウンタを3ch内蔵 ● カウント動作をバイナリ/BCDで設定 ● 6種類の動作モード IC collection i8253,i8254 http://www.itofamily.com/ito/collections/peripherals/i8253-54/
  42. 42. 2016/04/08 荒川 祐真 42 使用するハードウェアについて PIT(i8253あるいはi8254) ● 16bit長のカウンタを3ch内蔵 ● カウント動作をバイナリ/BCDで設定 ● 6種類の動作モード IC collection i8253,i8254 http://www.itofamily.com/ito/collections/peripherals/i8253-54/ 【BCD(Binary-Coded Decimal)】 ● 二進化十進表現 ● 16bit長を10進数4桁として扱う
  43. 43. 2016/04/08 荒川 祐真 43 使用するハードウェアについて PIT(i8253あるいはi8254) ● 16bit長のカウンタを3ch内蔵 ● カウント動作をバイナリ/BCDで設定 ● 6種類の動作モード IC collection i8253,i8254 http://www.itofamily.com/ito/collections/peripherals/i8253-54/
  44. 44. 2016/04/08 荒川 祐真 44 PITの動作モード OS5カーネルではモード2に設定 0から作るOS開発 割り込みその3 PICのまとめとPITと割り込みハンドラ http://softwaretechnique.jp/OS_Development/kernel_development04.html カウンタ 割り込み 0x0000
  45. 45. 2016/04/08 荒川 祐真 45 PITの動作モード OS5カーネルではモード2に設定 0から作るOS開発 割り込みその3 PICのまとめとPITと割り込みハンドラ http://softwaretechnique.jp/OS_Development/kernel_development04.html カウンタ 割り込み 0x2E9C カウンタに 値をセット
  46. 46. 2016/04/08 荒川 祐真 46 PITの動作モード OS5カーネルではモード2に設定 0から作るOS開発 割り込みその3 PICのまとめとPITと割り込みハンドラ http://softwaretechnique.jp/OS_Development/kernel_development04.html カウンタ 割り込み 0x2E9C AT互換機ではPITに1.19318MHzのクロックが与えられている。 とのことで、10ms毎にタイマー割り込みが発生するようにするため、 カウンタ値には11932(0x2E9C)を設定している。 (PIT)8254 - os-wiki http://oswiki.osask.jp/?(PIT)8254
  47. 47. 2016/04/08 荒川 祐真 47 PITの動作モード OS5カーネルではモード2に設定 0から作るOS開発 割り込みその3 PICのまとめとPITと割り込みハンドラ http://softwaretechnique.jp/OS_Development/kernel_development04.html カウンタ 割り込み 0x2E9C 0x0000
  48. 48. 2016/04/08 荒川 祐真 48 PITの動作モード OS5カーネルではモード2に設定 0から作るOS開発 割り込みその3 PICのまとめとPITと割り込みハンドラ http://softwaretechnique.jp/OS_Development/kernel_development04.html カウンタ 割り込み 0x2E9C 0x0000 タイマー 割り込み
  49. 49. 2016/04/08 荒川 祐真 49 PITの動作モード OS5カーネルではモード2に設定 0から作るOS開発 割り込みその3 PICのまとめとPITと割り込みハンドラ http://softwaretechnique.jp/OS_Development/kernel_development04.html カウンタ 割り込み 0x2E9C 0x0000 モード2だと、2回目以降は 自動でセットされる
  50. 50. 2016/04/08 荒川 祐真 50 PITの動作モード OS5カーネルではモード2に設定 0から作るOS開発 割り込みその3 PICのまとめとPITと割り込みハンドラ http://softwaretechnique.jp/OS_Development/kernel_development04.html カウンタ 割り込み 0x2E9C 0x0000
  51. 51. 2016/04/08 荒川 祐真 51 PITの動作モード OS5カーネルではモード2に設定 0から作るOS開発 割り込みその3 PICのまとめとPITと割り込みハンドラ http://softwaretechnique.jp/OS_Development/kernel_development04.html カウンタ 割り込み 0x2E9C 0x0000
  52. 52. 2016/04/08 荒川 祐真 52 PIT(i8254)の使い方 アセンブラのコード例 <コントロールレジスタ設定> out %al, $0x0043 <カウンタ0の読み出し> in $0x0040, %al PIT/Intel 8254 - OS Project Wiki http://www.wiki.os-project.jp/?PIT/Intel%208254&word=pit レジスタ一覧 I/Oポート R/W 内容 0x0040 R/W カウンタ0 0x0041 R/W カウンタ1 カウンタ2R/W0x0042 コントロール レジスタ W0x0043
  53. 53. 2016/04/08 荒川 祐真 53 実装 ● ソースコード – os5/kernel/timer.c – os5/kernel/include/timer.h
  54. 54. 2016/04/08 荒川 祐真 54 コード行数の推移 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数 【主な追加機能】 ● 時間管理 ● タスク管理 (スケジューラによる マルチタスク) ● アプリ(uptime)
  55. 55. 2016/04/08 荒川 祐真 55 OS5カーネルのアーキテクチャ カーネル 時間 管理 デバイスドライバ アプリ shell uptime コンソール CPU メモリ KBC CRTCPIT :機能の呼び出し関係 タスク管理 スケジューラ ソ フ ト ハ ー ド
  56. 56. 2016/04/08 荒川 祐真 56 タスクとは? ● OS5のカーネル上で実行される処理の単位 ● 現状は、shellとuptimeの2つ ● 現状、タスク=アプリケーション – カーネル内のタスク管理で話をするときはタスク – カーネルより上位で話をするときはアプリケーション
  57. 57. 2016/04/08 荒川 祐真 57 タスクの構造 タスクを管理する構造体: struct task os5/kernel/include/task.h
  58. 58. 2016/04/08 荒川 祐真 58 タスクの構造 タスクを管理する構造体: struct task os5/kernel/include/task.h
  59. 59. 2016/04/08 荒川 祐真 59 タスクの構造 タスクを管理する構造体: struct task os5/kernel/include/task.h 実行可能タスクを管理する 双方向リスト (ランキュー)
  60. 60. 2016/04/08 荒川 祐真 60 タスクの構造 タスクを管理する構造体: struct task os5/kernel/include/task.h タスクを一意に決める ID
  61. 61. 2016/04/08 荒川 祐真 61 タスクの構造 タスクを管理する構造体: struct task 以降のメンバは、 後ほど、登場する際に紹介
  62. 62. 2016/04/08 荒川 祐真 62 マルチタスク 複数のタスクをちょっとずつ、 切り替えながら実行 shell uptime shell uptime shell uptime 時間
  63. 63. 2016/04/08 荒川 祐真 63 マルチタスク 複数のタスクをちょっとずつ、 切り替えながら実行 shell uptime shell uptime shell uptime タイマー割り込み タイマー割り込み タイマー割り込み タイマー割り込み タイマー割り込み タイマー割り込み タイマー割り込み 10ms 時間
  64. 64. 2016/04/08 荒川 祐真 64 マルチタスク 複数のタスクをちょっとずつ、 切り替えながら実行 shell uptime shell uptime shell uptime タイマー割り込み タイマー割り込み タイマー割り込み タイマー割り込み タイマー割り込み タイマー割り込み タイマー割り込み 10ms 時間 「タイムスライス」 と呼ぶ
  65. 65. 2016/04/08 荒川 祐真 65 マルチタスク 複数のタスクをちょっとずつ、 切り替えながら実行 shell uptime shell uptime shell uptime タイマー割り込み タイマー割り込み タイマー割り込み タイマー割り込み タイマー割り込み タイマー割り込み タイマー割り込み 10ms スケジューラは いわば、 CPUの計算資源の 管理 時間
  66. 66. 2016/04/08 荒川 祐真 66 マルチタスク 複数のタスクをちょっとずつ、 切り替えながら実行 shell uptime shell uptime shell uptime タイマー割り込み タイマー割り込み タイマー割り込み タイマー割り込み タイマー割り込み タイマー割り込み タイマー割り込み 10ms スケジューラは いわば、 CPUの計算資源の 管理 時間 「コンテキストスイッチ」 と呼ぶ
  67. 67. 2016/04/08 荒川 祐真 67 コンテキストスイッチの流れ shell uptime 現在 実行中の タスク ランキュー struct task
  68. 68. 2016/04/08 荒川 祐真 68 コンテキストスイッチの流れ shell uptime 現在 実行中の タスク ランキュー コンテキストスイッチ イベント 発生
  69. 69. 2016/04/08 荒川 祐真 69 コンテキストスイッチの流れ shell uptime 現在 実行中の タスク ランキュー タスク管理 スケジューラ スケジューラは 次に実行するタスクを 選択 次に 実行する タスク
  70. 70. 2016/04/08 荒川 祐真 70 コンテキストスイッチの流れ shell uptime 現在 実行中の タスク ランキュー タスク管理 スケジューラ 次に 実行する タスク コンテキストスイッチ
  71. 71. 2016/04/08 荒川 祐真 71 コンテキストスイッチに必要なこと 今までshellを実行していたCPUを uptimeへスイッチするには 1.shellを再開するときのために、 情報を退避 2.退避していたuptimeの情報を 復帰 3.uptimeを再開
  72. 72. 2016/04/08 荒川 祐真 72 コンテキストスイッチに必要なこと 今までshellを実行していたCPUを uptimeへスイッチするには 1.shellを再開するときのために、 情報を退避 2.退避していたuptimeの情報を 復帰 3.uptimeを再開 このような情報をコンテキストと呼ぶ コンテキストに含まれるもの ● IP(インストラクションポインタ) ● フラグレジスタ ● スタックポインタ ● 汎用レジスタ
  73. 73. 2016/04/08 荒川 祐真 73 コンテキストスイッチに必要なこと 今までshellを実行していたCPUを uptimeへスイッチするには 1.shellを再開するときのために、 情報を退避 2.退避していたuptimeの情報を 復帰 3.uptimeを再開
  74. 74. 2016/04/08 荒川 祐真 74 コンテキストスイッチに必要なこと 今までshellを実行していたCPUを uptimeへスイッチするには 1.shellを再開するときのために、 情報を退避 2.退避していたuptimeの情報を 復帰 3.uptimeを再開 x86 CPUの タスク機能を 活用
  75. 75. 2016/04/08 荒川 祐真 75 x86のタスク機能 ● x86のCPUはタスクを管理する構造と機能を 持っている ● やってくれること – 命令1つで 1. 実行中タスクの退避 2. 次に実行するタスクの復帰 3. 実行再開 を行ってくれる
  76. 76. 2016/04/08 荒川 祐真 76 x86のタスク機能 ● x86のCPUはタスクを管理する構造と機能を 持っている ● やってくれること – 命令1つで 1. 実行中タスクの退避 2. 次に実行するタスクの復帰 3. 実行再開 を行ってくれる jmp TSSのアドレス
  77. 77. 2016/04/08 荒川 祐真 77 x86のタスク機能 ● x86のCPUはタスクを管理する構造と機能を 持っている ● やってくれること – 命令1つで 1. 実行中タスクの退避 2. 次に実行するタスクの復帰 3. 実行再開 を行ってくれる jmp TSSのアドレス 【TSS】 Task State Segment タスクの退避/復帰で 使用する領域
  78. 78. 2016/04/08 荒川 祐真 78 TSSの構造 TSSの構造 IA-32 インテル アー キテクチャ ソフトウェ ア・デベロッパーズ・ マニュアル(下巻), 図6-2 http://www.intel.c o.jp/content/dam/w ww/public/ijkk/jp/ ja/documents/devel oper/IA32_Arh_Dev_ Man_Vol3_i.pdf こんな形をしています
  79. 79. 2016/04/08 荒川 祐真 79 TSSの構造 TSSの構造 汎用レジスタ スタックポインタ CPUの特権レベル毎の スタックポインタ フラグレジスタ コンテキストに含まれるもの ● IP(インストラクションポインタ) ● フラグレジスタ ● スタックポインタ ● 汎用レジスタ IP IA-32 インテル アー キテクチャ ソフトウェ ア・デベロッパーズ・ マニュアル(下巻), 図6-2 http://www.intel.c o.jp/content/dam/w ww/public/ijkk/jp/ ja/documents/devel oper/IA32_Arh_Dev_ Man_Vol3_i.pdf
  80. 80. 2016/04/08 荒川 祐真 80 タスクの構造 タスクを管理する構造体: struct task
  81. 81. 2016/04/08 荒川 祐真 81 関連するソースコード ● スケジューラ – os5/kernel/sched.c – os5/kernel/include/sched.h ● タスク – os5/kernel/task.c – os5/kernel/include/task.h
  82. 82. 2016/04/08 荒川 祐真 82 コード行数の推移 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数 【主な追加機能】 ● メモリ管理 (ページング)
  83. 83. 2016/04/08 荒川 祐真 83 コード行数の推移 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数 【主な追加機能】 ● メモリ管理 (ページング)
  84. 84. 2016/04/08 荒川 祐真 84 カーネル 時間 管理 デバイスドライバ アプリ shell uptime コンソール CPU メモリ KBC CRTCPIT :機能の呼び出し関係 タスク管理 スケジューラ メモリ管理 ページング ソ フ ト ハ ー ド OS5カーネルのアーキテクチャ
  85. 85. 2016/04/08 荒川 祐真 85 OS5の現在のメモリマップ 物理アドレス空間 0x0000 0000 0xFFFF FFFF
  86. 86. 2016/04/08 荒川 祐真 86 OS5の現在のメモリマップ 物理アドレス空間 0x0000 0000 0xFFFF FFFF
  87. 87. 2016/04/08 荒川 祐真 87 OS5の現在のメモリマップ 物理アドレス空間 0x0000 0000 0xFFFF FFFF コンベンショナルメモリ領域 (640KB) 0x0000 0500 〜 0x0009 FFFF
  88. 88. 2016/04/08 荒川 祐真 88 OS5の現在のメモリマップ コンベンショナルメモリ 0x0000 0500 0x0009 FFFF OS5は現在、 このコンベンショナルメモリの領域 を想定し、動作している
  89. 89. 2016/04/08 荒川 祐真 89 OS5の現在のメモリマップ コンベンショナルメモリ 0x0000 0500 0x0009 FFFF カーネルバイナリ配置領域 (36.5KB) 0x0000 7E00 〜 0x0001 0FFF ユーザーランド配置領域 (12.0KB) 0x0001 1000 〜 0x0001 3FFF
  90. 90. 2016/04/08 荒川 祐真 90 OS5の現在のメモリマップ コンベンショナルメモリ 0x0000 0500 0x0009 FFFF カーネルバイナリ配置領域 (36.5KB) 0x0000 7E00 〜 0x0001 0FFF ユーザーランド配置領域 (12.0KB) 0x0001 1000 〜 0x0001 3FFF カーネルやブートローダーを 配置する領域とは別の領域 ファイルシステムを用意し、 ファイルを配置する 現状は、shellとuptimeの 実行ファイルのみ
  91. 91. 2016/04/08 荒川 祐真 91 OS5の現在のメモリマップ コンベンショナルメモリ 0x0000 0500 0x0009 FFFF カーネルスタック領域 (436.0KB) 0x0001 3000 〜 0x0007 FFFF カーネル用ページテーブル配置領域 (8.0KB) 0x0008 F000 〜 0x0009 0FFF 0x0008 0000
  92. 92. 2016/04/08 荒川 祐真 92 OS5の現在のメモリマップ コンベンショナルメモリ 0x0000 0500 0x0009 FFFF ヒープ領域 (44.0KB) 0x0009 5000 〜 0x0009 FFFF 0x0008 0000
  93. 93. 2016/04/08 荒川 祐真 93 ページングとは? 物理アドレス空間を固定長(4KB)毎に分割 それぞれに、物理アドレスとは別のアドレス (仮想アドレス)を割り当て、 メモリを管理する仕組み
  94. 94. 2016/04/08 荒川 祐真 94 ページングとは? 物理アドレス空間 ※ 表示の都合上、   コンベンショナルメモリ領域を   拡大 0x0000 0500 0x0009 FFFF 0x0008 0000
  95. 95. 2016/04/08 荒川 祐真 95 ページングとは? 物理アドレス空間 ※ 表示の都合上、   コンベンショナルメモリ領域を   拡大 0x0000 0500 0x0009 FFFF 0x0008 0000 ユーザーランド配置領域 (12.0KB) 0x0001 1000 〜 0x0001 3FFF
  96. 96. 2016/04/08 荒川 祐真 96 ページングとは? 物理アドレス空間 ※ 表示の都合上、   ユーザーランド領域を   拡大 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 ファイルシステムコントロールブロック (4KB) 0x0001 1000 〜 0x0001 1FFF shell (3.3KB) 0x0001 2000 〜 0x0001 2CEB uptime (316B) 0x0001 3000 〜 0x0001 313B
  97. 97. 2016/04/08 荒川 祐真 97 ページングとは? 物理アドレス空間 ※ 表示の都合上、   ユーザーランド領域を   拡大 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 物理アドレス空間全体 (0x0000 0000 〜 0xFFFF FFFF)を、 4KB単位で分割 分割した 各4KBの領域を 「ページ」と呼ぶ
  98. 98. 2016/04/08 荒川 祐真 98 ページングとは? 物理アドレス空間 ※ 表示の都合上、   ユーザーランド領域を   拡大 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 仮想アドレス(VA)を 物理アドレス(PA)へ変換する 変換表を用意 VA PA 0x2000 0000 0x0001 2000
  99. 99. 2016/04/08 荒川 祐真 99 ページングとは? 物理アドレス空間 ※ 表示の都合上、   ユーザーランド領域を   拡大 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 仮想アドレス(VA)を 物理アドレス(PA)へ変換する 変換表を用意 VA PA 0x2000 0000 0x0001 2000 ※ ちなみに、VAにPAを対応付けることを、   「マップする」と言う
  100. 100. 2016/04/08 荒川 祐真 100 ページングとは? 物理アドレス空間 ※ 表示の都合上、   ユーザーランド領域を   拡大 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 ページング有効化! VA PA 0x2000 0000 0x0001 2000 MMU 【Memory Management Unit】 アドレス変換を行ってくれる ハードウェア
  101. 101. 2016/04/08 荒川 祐真 101 ページングとは? 物理アドレス空間 ※ 表示の都合上、   ユーザーランド領域を   拡大 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 CPUはMMUを介して メモリアクセス VA PA 0x2000 0000 0x0001 2000 MMU
  102. 102. 2016/04/08 荒川 祐真 102 ページングとは? 物理アドレス空間 ※ 表示の都合上、   ユーザーランド領域を   拡大 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 = MMUは CPUがアクセスするアドレス(VA)を PAに変換 VA PA 0x2000 0000 0x0001 2000 MMU
  103. 103. 2016/04/08 荒川 祐真 103 ページングとは? 物理アドレス空間 ※ 表示の都合上、   ユーザーランド領域を   拡大 0x0001 1000 0x0001 3FFF = 0x0001 2000 0x0001 3000 MMUは CPUがアクセスするアドレス(VA)を PAに変換 VA PA 0x2000 0000 0x0001 2000 MMU
  104. 104. 2016/04/08 荒川 祐真 104 ページングとは? 物理アドレス空間 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000変換表をタスク毎に用意すれば、 ● カーネルは各タスクの実行時のアドレスを 統一できる ● 原理上、他のタスクのメモリ領域を 破壊できなくなる(タスク間メモリ保護) VA PA 0x2000 0000 0x0001 2000 shell用 VA PA 0x2000 0000 0x0001 3000 uptime用
  105. 105. 2016/04/08 荒川 祐真 105 仮想アドレス空間のメモリマップ 0x0000 0000 0xFFFF FFFF カーネル 空間 ユーザ 空間 0x2000 0000 仮 想 ア ド レ ス 空 間 コンベンショナル メモリ領域 物 理 ア ド レ ス 空 間
  106. 106. 2016/04/08 荒川 祐真 106 仮想アドレス空間のメモリマップ 0x0000 0000 0xFFFF FFFF カーネル 空間 ユーザ 空間 0x2000 0000 仮 想 ア ド レ ス 空 間 コンベンショナル メモリ領域 物 理 ア ド レ ス 空 間 VA=PA カーネル空間から 全ての資源にアクセス可
  107. 107. 2016/04/08 荒川 祐真 107 仮想アドレス空間のメモリマップ 0x0000 0000 0xFFFF FFFF カーネル 空間 ユーザ 空間 0x2000 0000 仮 想 ア ド レ ス 空 間 物 理 ア ド レ ス 空 間 shell uptime VAは 現在実行中のタスクに マップされる (この場合shell)
  108. 108. 2016/04/08 荒川 祐真 108 VA→PA変換のまとめ IA-32 インテル アーキテクチャ ソフトウェア・デベロッパーズ・マニュアル(下巻), 図3-12 http://www.intel.co.jp/content/dam/www/public/ijkk/jp/ja/documents/developer/ IA32_Arh_Dev_Man_Vol3_i.pdf VAのこと
  109. 109. 2016/04/08 荒川 祐真 109 VA→PA変換のまとめ ページ・ディレクトリ (PD) ページ・ディレクトリ・ エントリ (PDE) ページ・テーブル (PT) ページ・テーブル・ エントリ (PTE) IA-32 インテル アーキテクチャ ソフトウェア・デベロッパーズ・マニュアル(下巻), 図3-12 http://www.intel.co.jp/content/dam/www/public/ijkk/jp/ja/documents/developer/ IA32_Arh_Dev_Man_Vol3_i.pdf
  110. 110. 2016/04/08 荒川 祐真 110 shellとuptimeのPD・PTについて ページテーブルページディレクトリ ページ カーネル shell uptime shell用 uptime用 shell用 uptime用 カーネル用
  111. 111. 2016/04/08 荒川 祐真 111 shellとuptimeのPD・PTについて ページテーブルページディレクトリ ページ カーネル shell uptime shell用 uptime用 shell用 uptime用 カーネル用 共通のPTを使用
  112. 112. 2016/04/08 荒川 祐真 112 shellとuptimeのPD・PTについて ページテーブルページディレクトリ ページ カーネル shell uptime shell用 uptime用 shell用 uptime用 カーネル用 タスク毎のPD切り替えも コンテキストスイッチ時に CPUが自動で行う
  113. 113. 2016/04/08 荒川 祐真 113 PD・PTもメモリ上に存在する コンベンショナルメモリ 0x0000 0500 0x0009 FFFF 0x0008 0000 カーネル用ページテーブル配置領域 (8.0KB) 0x0008 F000 〜 0x0009 0FFF ヒープ領域 (44.0KB) 0x0009 5000 〜 0x0009 FFFF shell・uptimeのPD・PTは タスク生成時に 動的確保
  114. 114. 2016/04/08 荒川 祐真 114 PDE・PTEの実体 IA-32 インテル アーキテクチャ ソフトウェア・デベロッパーズ・マニュアル(下巻), 図3-14 http://www.intel.co.jp/content/dam/www/public/ijkk/jp/ja/documents/developer/IA32 _Arh_Dev_Man_Vol3_i.pdf
  115. 115. 2016/04/08 荒川 祐真 115 PDE・PTEの実体 IA-32 インテル アーキテクチャ ソフトウェア・デベロッパーズ・マニュアル(下巻), 図3-14 http://www.intel.co.jp/content/dam/www/public/ijkk/jp/ja/documents/developer/IA32 _Arh_Dev_Man_Vol3_i.pdf
  116. 116. 2016/04/08 荒川 祐真 116 関連するソースコード ● os5/kernel/memory.c ● os5/kernel/include/memory.h
  117. 117. 2016/04/08 荒川 祐真 117 OS5の機能構成(ソースコード構成) 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数 【主な追加機能】 ● タスク管理 (スケジューラによる タスクスリープ/ウェイクアップ) ● 省電力機能 ● 特権管理 ● システムコール
  118. 118. 2016/04/08 荒川 祐真 118 OS5の機能構成(ソースコード構成) 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数 【主な追加機能】 ● タスク管理 (スケジューラによる タスクスリープ/ウェイクアップ) ● 省電力機能 ● 特権管理 ● システムコール
  119. 119. 2016/04/08 荒川 祐真 119 カーネル 時間 管理 デバイスドライバ アプリ shell uptime コンソール CPU メモリ KBC CRTCPIT :機能の呼び出し関係 タスク管理 スケジューラ メモリ管理 ページング ソ フ ト ハ ー ド OS5カーネルのアーキテクチャ
  120. 120. 2016/04/08 荒川 祐真 120 タスクのスリープについて ● タスクだって寝たい時がある – 「XX分後に起こしてー」 – 「XXがあったら起こしてー」
  121. 121. 2016/04/08 荒川 祐真 121 タスクのスリープについて ● タスクだって寝たい時がある – 「XX分後に起こしてー」 – 「XXがあったら起こしてー」 OS5では、タスクについて、以下を登録できる ・ウェイクアップタイマー ・ウェイクアップイベント
  122. 122. 2016/04/08 荒川 祐真 122 タスクのスリープについて ● ウェイクアップタイマー(目覚し時計) – 関数: wakeup_after_msec(unsigned int msec) – 「XXms後に起こしてー」 ● ウェイクアップイベント(目覚ましイベント) – 関数: wakeup_after_event(unsigned char event_type) – 「XXが起きたら起こしてー」 – 今、対応しているイベントは「キーボード入力」のみ
  123. 123. 2016/04/08 荒川 祐真 123 タスクのスリープについて どのように実現しているのか?
  124. 124. 2016/04/08 荒川 祐真 124 タスクのスリープについて どのように実現しているのか? ランキューから抜いたり追加したりする
  125. 125. 2016/04/08 荒川 祐真 125 タスクのスリープについて どのように実現しているのか? ランキュー shell uptime
  126. 126. 2016/04/08 荒川 祐真 126 タスクのスリープについて どのように実現しているのか? ランキュー shell uptime 33ms後に 起こしてー ※ タイマー割り込みの粒度が10msなので、   実際は40ms後に起こされる
  127. 127. 2016/04/08 荒川 祐真 127 タスクのスリープについて どのように実現しているのか? ランキュー shell uptime ウェイクアップキュー
  128. 128. 2016/04/08 荒川 祐真 128 タスクのスリープについて どのように実現しているのか? ランキュー shell uptime ウェイクアップキュー 以降、shellのみ実行
  129. 129. 2016/04/08 荒川 祐真 129 タスクのスリープについて どのように実現しているのか? ランキュー shell uptime ウェイクアップキュー タイマー割り込み発生 33ms以上経過
  130. 130. 2016/04/08 荒川 祐真 130 タスクのスリープについて どのように実現しているのか? ランキュー shell uptime ウェイクアップキュー ランキューに戻す
  131. 131. 2016/04/08 荒川 祐真 131 タスクの構造 タスクを管理する構造体: struct task ウェイクアップキュー への追加時の ウェイクアップ要因 管理用 unsigned int wakeup_after_msec; unsigned char wakeup_after_event;
  132. 132. 2016/04/08 荒川 祐真 132 スリープでのコンテキストスイッチ による問題 時間 10ms 10ms 10ms タイマー割り込み によるコンテキストスイッチ
  133. 133. 2016/04/08 荒川 祐真 133 時間 10ms 10ms 10ms shell キー入力待ち スリープでのコンテキストスイッチ による問題
  134. 134. 2016/04/08 荒川 祐真 134 時間 10ms 10ms 10ms shell uptime ちょっとしか 実行できない・・・ スリープでのコンテキストスイッチ による問題
  135. 135. 2016/04/08 荒川 祐真 135 ● 自らスリープした時は、 「タイムスライスの残りを他タスクにプレゼント」と判断 時間 10ms 10ms 10ms shell uptime uptime スリープでのコンテキストスイッチ による問題
  136. 136. 2016/04/08 荒川 祐真 136 タスクの構造 タスクを管理する構造体: struct task コンテキストスイッチ時、 タイムスライスを 使い切ったか否かの 判別用 char task_switched_in_time_slice;
  137. 137. 2016/04/08 荒川 祐真 137 OS5の機能構成(ソースコード構成) 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数 【主な追加機能】 ● タスク管理 (スケジューラによる タスクスリープ/ウェイクアップ) ● 省電力機能 ● 特権管理 ● システムコール
  138. 138. 2016/04/08 荒川 祐真 138 カーネル 時間 管理 デバイスドライバ アプリ shell uptime コンソール CPU メモリ KBC CRTCPIT :機能の呼び出し関係 タスク管理 スケジューラ メモリ管理 ページング ソ フ ト ハ ー ド OS5カーネルのアーキテクチャ
  139. 139. 2016/04/08 荒川 祐真 139 カーネルタスク ● 省電力機能 ランキューに何も無いときには、カーネルタスクを実行 ランキュー 空 カーネル タスク
  140. 140. 2016/04/08 荒川 祐真 140 カーネルタスク ● 省電力機能 ランキューに何も無いときには、カーネルタスクを実行 ランキュー 空 カーネル タスク hlt命令を実行 割り込みがあるまで CPUを休ませる
  141. 141. 2016/04/08 荒川 祐真 141 関連するソースコード ● カーネルタスク – os5/kernel/kern_task_init.c – os5/kernel/include/kern_task.h ● カーネル初期化 – os5/kernel/init.c
  142. 142. 2016/04/08 荒川 祐真 142 関連するソースコード ● カーネルタスク – os5/kernel/kern_task_init.c – os5/kernel/include/kern_task.h ● カーネル初期化 – os5/kernel/init.c
  143. 143. 2016/04/08 荒川 祐真 143 関連するソースコード ● カーネルタスク – os5/kernel/kern_task_init.c – os5/kernel/include/kern_task.h ● カーネル初期化 – os5/kernel/init.c カーネル初期化関数(kern_init)が カーネルの初期化後、 カーネルタスクとして振る舞う kern_init関数の末尾
  144. 144. 2016/04/08 荒川 祐真 144 コード行数の推移 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数 【主な追加機能】 ● タスク管理 (スケジューラによる タスクスリープ/ウェイクアップ) ● 省電力機能 ● 特権管理 ● システムコール
  145. 145. 2016/04/08 荒川 祐真 145 カーネル 時間 管理 デバイスドライバ アプリ shell uptime コンソール CPU メモリ KBC CRTCPIT :機能の呼び出し関係 タスク管理 スケジューラ メモリ管理 ページング ソ フ ト ハ ー ド OS5カーネルのアーキテクチャ
  146. 146. 2016/04/08 荒川 祐真 146 x86 CPUの特権レベル ● x86 CPUには0〜3の4つの特権レベルがある – 番号が大きくなると、特権が低くなる ● OS5カーネルでは0と3の特権レベルを使用 – カーネル: 特権レベル0 – タスク : 特権レベル3 ● 特権レベルは、 TSSを定義するセグメントディスクリプタに設定
  147. 147. 2016/04/08 荒川 祐真 147 x86 CPUの特権レベル ● x86 CPUには0〜3の4つの特権レベルがある – 番号が大きくなると、特権が低くなる ● OS5カーネルでは0と3の特権レベルを使用 – カーネル: 特権レベル0 – タスク : 特権レベル3 ● 特権レベルは、 TSSを定義するセグメントディスクリプタに設定
  148. 148. 2016/04/08 荒川 祐真 148 そもそも、「セグメント」とは 【セグメンテーション】 ● アドレス空間を「ベースアドレス」と「リミット」で分割し、 管理する方式 ● 分割した領域を「セグメント」と呼ぶ
  149. 149. 2016/04/08 荒川 祐真 149 そもそも、「セグメント」とは IA-32 インテル アーキテクチャ ソフトウェア・デベロッパーズ・ マニュアル(下巻), 図3-1 http://www.intel.co.jp/content/dam/www/public/ijkk/jp/ja/ documents/developer/IA32_Arh_Dev_Man_Vol3_i.pdf セグメント
  150. 150. 2016/04/08 荒川 祐真 150 そもそも、「セグメント」とは セグメント セグメント ディスクリプタ IA-32 インテル アーキテクチャ ソフトウェア・デベロッパーズ・ マニュアル(下巻), 図3-1 http://www.intel.co.jp/content/dam/www/public/ijkk/jp/ja/ documents/developer/IA32_Arh_Dev_Man_Vol3_i.pdf
  151. 151. 2016/04/08 荒川 祐真 151 セグメントディスクリプタ IA-32 インテル アーキテクチャ ソフトウェア・デベロッパーズ・マニュアル(下巻), 図3-8 http://www.intel.co.jp/content/dam/www/public/ijkk/jp/ja/documents/developer/IA32_Arh_Dev _Man_Vol3_i.pdf
  152. 152. 2016/04/08 荒川 祐真 152 セグメントディスクリプタ IA-32 インテル アーキテクチャ ソフトウェア・デベロッパーズ・マニュアル(下巻), 図3-8 http://www.intel.co.jp/content/dam/www/public/ijkk/jp/ja/documents/developer/IA32_Arh_Dev _Man_Vol3_i.pdf ベースアドレスとリミットは、 セグメントディスクリプタに含まれている
  153. 153. 2016/04/08 荒川 祐真 153 セグメントディスクリプタ IA-32 インテル アーキテクチャ ソフトウェア・デベロッパーズ・マニュアル(下巻), 図3-8 http://www.intel.co.jp/content/dam/www/public/ijkk/jp/ja/documents/developer/IA32_Arh_Dev _Man_Vol3_i.pdf 特権レベルはここに設定する
  154. 154. 2016/04/08 荒川 祐真 154 【再掲】PDE・PTEの実体 IA-32 インテル アーキテクチャ ソフトウェア・デベロッパーズ・マニュアル, 図3-14 http://www.intel.co.jp/content/dam/www/public/ijkk/jp/ja/documents/developer/IA32_Arh_ Dev_Man_Vol3_i.pdf
  155. 155. 2016/04/08 荒川 祐真 155 【再掲】PDE・PTEの実体 カーネルのページでは スーパーバイザ(=0)に、 タスクのページでは、 ユーザ(=1)に設定 IA-32 インテル アーキテクチャ ソフトウェア・デベロッパーズ・マニュアル, 図3-14 http://www.intel.co.jp/content/dam/www/public/ijkk/jp/ja/documents/developer/IA32_Arh_ Dev_Man_Vol3_i.pdf
  156. 156. 2016/04/08 荒川 祐真 156 【再掲】PDE・PTEの実体 カーネルのページでは スーパーバイザ(=0)に、 タスクのページでは、 ユーザ(=1)に設定 PDE・PTEのU/Sビットと 特権レベルの対応 0 1 2 3 0 1 U/Sビット 特権レベル IA-32 インテル アーキテクチャ ソフトウェア・デベロッパーズ・マニュアル, 図3-14 http://www.intel.co.jp/content/dam/www/public/ijkk/jp/ja/documents/developer/IA32_Arh_ Dev_Man_Vol3_i.pdf
  157. 157. 2016/04/08 荒川 祐真 157 【再掲】PDE・PTEの実体 カーネルのページでは スーパーバイザ(=0)に、 タスクのページでは、 ユーザ(=1)に設定 PDE・PTEのU/Sビットと 特権レベルの対応 0 1 2 3 0 1 U/Sビット 特権レベル タスクの特権レベル設定と、 ページのU/Sビット設定の組み合わせで メモリ保護が実現できる IA-32 インテル アーキテクチャ ソフトウェア・デベロッパーズ・マニュアル, 図3-14 http://www.intel.co.jp/content/dam/www/public/ijkk/jp/ja/documents/developer/IA32_Arh_ Dev_Man_Vol3_i.pdf
  158. 158. 2016/04/08 荒川 祐真 158 コード行数の推移 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数 【主な追加機能】 ● タスク管理 (スケジューラによる タスクスリープ/ウェイクアップ) ● 省電力機能 ● 特権管理 ● システムコール
  159. 159. 2016/04/08 荒川 祐真 159 カーネル 時間 管理 システムコール デバイスドライバ アプリ shell uptime コンソール CPU メモリ KBC CRTCPIT :機能の呼び出し関係 タスク管理 スケジューラ メモリ管理 ページング ソ フ ト ハ ー ド OS5カーネルのアーキテクチャ
  160. 160. 2016/04/08 荒川 祐真 160 システムコールとは ● OS5において、 アプリケーションがカーネルとやり取りする ための唯一のインタフェース
  161. 161. 2016/04/08 荒川 祐真 161 実装 ● アプリケーションは ユーザーの特権レベルで動作 ● カーネル空間の関数を呼ぶことはできない ● カーネル空間の機能を呼び出すために、 「ソフトウェア割り込み」を使用
  162. 162. 2016/04/08 荒川 祐真 162 動作例 shell kernel 3 現在の特権レベル EAX EBX ECX EDX 汎用レジスタ
  163. 163. 2016/04/08 荒川 祐真 163 動作例 shell kernel 3 現在の特権レベル EAX EBX ECX EDX 汎用レジスタ shell動作中
  164. 164. 2016/04/08 荒川 祐真 164 動作例 shell kernel 3 現在の特権レベル EAX EBX ECX EDX 汎用レジスタ “Hello”と 画面に表示したい
  165. 165. 2016/04/08 荒川 祐真 165 動作例 shell kernel 3 現在の特権レベル EAX EBX ECX EDX 汎用レジスタ CON_PUT_STR システムコール (文字列をコンソール上に 出力するシステムコール) を実行したい
  166. 166. 2016/04/08 荒川 祐真 166 動作例 shell kernel 3 現在の特権レベル EAX EBX ECX EDX 汎用レジスタ 【前提条件】 アプリケーションとカーネルの間で、 以下の合意が取れている ● システムコールに使用する割り込み番号 ● 汎用レジスタを使用した値受け渡し方法
  167. 167. 2016/04/08 荒川 祐真 167 動作例 shell kernel 3 現在の特権レベル CON_PUT_STR(定数)EAX “Hello”の先頭アドレスEBX ECX EDX 汎用レジスタ EAXにシステムコールIDを、 EBX〜EDXに第1〜第3引数を設定
  168. 168. 2016/04/08 荒川 祐真 168 動作例 shell kernel 3 現在の特権レベル CON_PUT_STR(定数)EAX “Hello”の先頭アドレスEBX ECX EDX 汎用レジスタ int $0x80 ソフトウェア割り込み実行 ※ OS5カーネルでは、0x80番のソフトウェア割り込みを  システムコールとして使用する
  169. 169. 2016/04/08 荒川 祐真 169 動作例 shell kernel 0 現在の特権レベル CON_PUT_STR(定数)EAX “Hello”の先頭アドレスEBX ECX EDX 汎用レジスタ 特権レベル昇格 0x80番の割り込みハンドラ が呼び出される
  170. 170. 2016/04/08 荒川 祐真 170 動作例 shell kernel 0 現在の特権レベル CON_PUT_STR(定数)EAX “Hello”の先頭アドレスEBX ECX EDX 汎用レジスタ 割り込みハンドラ内で 以下を実行 1. EAXで対象の  システムコールを確認 2. システムコールに対応  するカーネル内の関数  を実行 3. 戻り値をEAXに設定 4. 割り込みからリターン
  171. 171. 2016/04/08 荒川 祐真 171 動作例 shell kernel 3 現在の特権レベル CON_PUT_STR(定数)EAX “Hello”の先頭アドレスEBX ECX EDX 汎用レジスタ 元の特権レベルに戻る
  172. 172. 2016/04/08 荒川 祐真 172 現在のシステムコール一覧 システムコール定数名 機能 TIMER_GET_GLOBAL_COUNTER 時間管理: グローバルカウンタ値取得 SCHED_WAKEUP_MSEC タスク管理(スケジューラ): ウェイクアップ時間を指定し、ス リープ CON_GET_CURSOR_POS_Y デバイスドライバ(コンソール): カーソル位置のY座標値取 得 CON_PUT_STR デバイスドライバ(コンソール): 文字列表示 CON_PUT_STR_POS デバイスドライバ(コンソール): 文字列表示(座標指定) CON_DUMP_HEX デバイスドライバ(コンソール): 指定した数値を16進数で表 示 CON_DUMP_HEX_POS デバイスドライバ(コンソール): 指定した数値を16進数で表 示(座標指定) CON_GET_LINE デバイスドライバ(コンソール): 1行の入力を取得 OPEN ファイルシステム: ファイルを開く EXEC ファイルシステム: ファイルを実行する
  173. 173. 2016/04/08 荒川 祐真 173 現在のシステムコール一覧 システムコール定数名 機能 TIMER_GET_GLOBAL_COUNTER 時間管理: グローバルカウンタ値取得 SCHED_WAKEUP_MSEC タスク管理(スケジューラ): ウェイクアップ時間を指定し、ス リープ CON_GET_CURSOR_POS_Y デバイスドライバ(コンソール): カーソル位置のY座標値取 得 CON_PUT_STR デバイスドライバ(コンソール): 文字列表示 CON_PUT_STR_POS デバイスドライバ(コンソール): 文字列表示(座標指定) CON_DUMP_HEX デバイスドライバ(コンソール): 指定した数値を16進数で表 示 CON_DUMP_HEX_POS デバイスドライバ(コンソール): 指定した数値を16進数で表 示(座標指定) CON_GET_LINE デバイスドライバ(コンソール): 1行の入力を取得 OPEN ファイルシステム: ファイルを開く EXEC ファイルシステム: ファイルを実行する システムコール部分の完成度としては、 まだ「システムコールの枠組みができあがった」くらい 「カーネルとしてどのようなシステムコールを用意するか」 という観点で、 システムコールのラインナップ自体は今後変更していく予定
  174. 174. 2016/04/08 荒川 祐真 174 関連するソースコード ● os5/kernel/sys.S ● os5/kernel/syscall.c ● os5/kernel/include/syscall.h
  175. 175. 2016/04/08 荒川 祐真 175 コード行数の推移 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数 【主な追加機能】 ● ファイルシステム ● メモリ管理 (メモリアロケータ) ● タスク管理 (タスクローダ)
  176. 176. 2016/04/08 荒川 祐真 176 コード行数の推移 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数 【主な追加機能】 ● ファイルシステム ● メモリ管理 (メモリアロケータ) ● タスク管理 (タスクローダ)
  177. 177. 2016/04/08 荒川 祐真 177 カーネル 時間 管理 ファイルシステム システムコール デバイスドライバ アプリ shell uptime コンソール CPU メモリ KBC CRTCPIT :機能の呼び出し関係 タスク管理 スケジューラ メモリ管理 ページング ソ フ ト ハ ー ド OS5カーネルのアーキテクチャ
  178. 178. 2016/04/08 荒川 祐真 178 なんのためのもの? ● 単なるバイナリ列を、 「ファイル」として扱うためのルール決め ● OS5の場合、全てのデータは、 ブートローダーがRAMにロードする ● RAM上の「ユーザーランド領域」の バイナリ列のルールを決めている
  179. 179. 2016/04/08 荒川 祐真 179 OS5の現在のファイルシステム ユーザーランド領域 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 ファイルシステムコントロールブロック (4KB) 0x0001 1000 〜 0x0001 1FFF shell (3.3KB) 0x0001 2000 〜 0x0001 2CEB uptime (316B) 0x0001 3000 〜 0x0001 313B
  180. 180. 2016/04/08 荒川 祐真 180 OS5の現在のファイルシステム ユーザーランド領域 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 【ルール1】 先頭4KBにコントロールブロックを 配置
  181. 181. 2016/04/08 荒川 祐真 181 OS5の現在のファイルシステム ユーザーランド領域 0x0001 1000 0x0001 3FFF 2 0x0001 2000 0x0001 3000 【ルール2】 コントロールブロックには 存在するファイル数を格納
  182. 182. 2016/04/08 荒川 祐真 182 OS5の現在のファイルシステム ユーザーランド領域 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 【ルール3】 ファイルは4KB以内 4KB 4KB
  183. 183. 2016/04/08 荒川 祐真 183 OS5の現在のファイルシステム ユーザーランド領域 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 【ルール4】 ファイルの先頭32バイトに ファイル名を格納 shell uptime
  184. 184. 2016/04/08 荒川 祐真 184 OS5の現在のファイルシステム ユーザーランド領域 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 【ルール5】 ファイルの先頭33バイト以降に ファイル本体を格納 ファイル本体を 配置
  185. 185. 2016/04/08 荒川 祐真 185 OS5の現在のファイルシステム ユーザーランド領域 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 【ルール6】 ファイルを実行する際は、 先頭33バイト目にジャンプする
  186. 186. 2016/04/08 荒川 祐真 186 OS5の現在のファイルシステム ユーザーランド領域 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 【ルール6】 ファイルを実行する際は、 先頭33バイト目にジャンプする os5/apps/app.lc
  187. 187. 2016/04/08 荒川 祐真 187 OS5の現在のファイルシステム ユーザーランド領域 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 【ルール6】 ファイルを実行する際は、 先頭33バイト目にジャンプする os5/apps/app.lc 0x2000 0000 (アプリバイナリを 配置する先頭のVA) + 0x20 (32バイト分飛ばした先)
  188. 188. 2016/04/08 荒川 祐真 188 OS5の現在のファイルシステム ユーザーランド領域 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 【ルール6】 ファイルを実行する際は、 先頭33バイト目にジャンプする os5/apps/app.lc textセクション (コンパイル結果の機械語を 配置するセクション)を 先頭に配置
  189. 189. 2016/04/08 荒川 祐真 189 OS5の現在のファイルシステム ユーザーランド領域 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 【ルール6】 ファイルを実行する際は、 先頭33バイト目にジャンプする os5/apps/app.lc textセクション (コンパイル結果の機械語を 配置するセクション)を 先頭に配置 加えて、エントリとなる関数 (shell_start()、uptime_start())は、 各ソースコード(shell.c、uptime.c)の 一番先頭で定義
  190. 190. 2016/04/08 荒川 祐真 190 OS5の現在のファイルシステム ユーザーランド領域 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 【ルール6】 ファイルを実行する際は、 先頭33バイト目にジャンプする TSSの一部 EIP
  191. 191. 2016/04/08 荒川 祐真 191 OS5の現在のファイルシステム ユーザーランド領域 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 【ルール6】 ファイルを実行する際は、 先頭33バイト目にジャンプする TSSの一部 EIP タスク初期化時、 EIPに 0x2000 0020 を設定
  192. 192. 2016/04/08 荒川 祐真 192 ファイルの構造 ファイルを管理する構造体: struct file
  193. 193. 2016/04/08 荒川 祐真 193 ファイルの構造 ファイルを管理する構造体: struct file
  194. 194. 2016/04/08 荒川 祐真 194 ファイルシステムの初期化 ファイルシステム内を検索し、 struct fileのリンクリストを作成 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 shell uptime
  195. 195. 2016/04/08 荒川 祐真 195 ファイルシステムの初期化 struct listshellの struct file next prev char *name void *data_bas_addr 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 shell uptimestruct listuptimeの struct file next prev char *name void *data_bas_addr
  196. 196. 2016/04/08 荒川 祐真 196 ファイルシステムの初期化 struct listshellの struct file next prev char *name void *data_bas_addr 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 shell uptimestruct listuptimeの struct file next prev char *name void *data_bas_addr
  197. 197. 2016/04/08 荒川 祐真 197 ファイルシステムの初期化 struct listshellの struct file next prev char *name void *data_bas_addr 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 shell uptimestruct listuptimeの struct file next prev char *name void *data_bas_addr
  198. 198. 2016/04/08 荒川 祐真 198 ファイルシステムの初期化 struct listshellの struct file next prev char *name void *data_bas_addr 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 shell uptimestruct listuptimeの struct file next prev char *name void *data_bas_addr
  199. 199. 2016/04/08 荒川 祐真 199 関連するソースコード ● os5/kernel/fs.c ● os5/kernel/include/fs.h ● os5/tools/make_os5_fs.sh – アプリケーションバイナリから ファイルシステムを生成する シェルスクリプト
  200. 200. 2016/04/08 荒川 祐真 200 コード行数の推移 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数 【主な追加機能】 ● ファイルシステム ● メモリ管理 (メモリアロケータ) ● タスク管理 (タスクローダ)
  201. 201. 2016/04/08 荒川 祐真 201 カーネル 時間 管理 ファイルシステム システムコール デバイスドライバ アプリ shell uptime コンソール CPU メモリ KBC CRTCPIT :機能の呼び出し関係 タスク管理 スケジューラ メモリ管理 ページング メモリアロケータ ソ フ ト ハ ー ド OS5カーネルのアーキテクチャ
  202. 202. 2016/04/08 荒川 祐真 202 メモリアロケータ ● どのようなものか? – メモリ上にヒープ領域を設定 – メモリの動的確保を要求された時、 ヒープ領域からメモリを確保し、要求者へ与える ● OS5の場合、固定長(4KB) – ヒープ領域内の使用状況の管理も行う
  203. 203. 2016/04/08 荒川 祐真 203 メモリアロケータ コンベンショナルメモリ 0x0000 0500 0x0009 FFFF ヒープ領域 (44.0KB) 0x0009 5000 〜 0x0009 FFFF 0x0008 0000
  204. 204. 2016/04/08 荒川 祐真 204 メモリアロケータ ヒープ領域 0x0009 5000 0x0009 FFFF
  205. 205. 2016/04/08 荒川 祐真 205 メモリアロケータ ヒープ領域 0x0009 5000 0x0009 FFFF 固定長(4KB)で分割
  206. 206. 2016/04/08 荒川 祐真 206 メモリアロケータ ヒープ領域 0x0009 5000 0x0009 FFFF メモリ動的確保の要求があれば、 4KBずつ与える タスク管理 uptimeタスク用に スタック領域を 確保したい
  207. 207. 2016/04/08 荒川 祐真 207 メモリアロケータ ヒープ領域 0x0009 5000 0x0009 FFFF メモリ動的確保の要求があれば、 4KBずつ与える タスク管理 メモリちょうだい mem_alloc() メモリ アロケータ
  208. 208. 2016/04/08 荒川 祐真 208 メモリアロケータ ヒープ領域 0x0009 5000 0x0009 FFFF メモリ動的確保の要求があれば、 4KBずつ与える タスク管理 メモリ アロケータ 使ってないヤツ 見つけた!
  209. 209. 2016/04/08 荒川 祐真 209 メモリアロケータ ヒープ領域 0x0009 5000 0x0009 FFFF メモリ動的確保の要求があれば、 4KBずつ与える タスク管理 メモリ アロケータ 使用中の目印を 付けておこう
  210. 210. 2016/04/08 荒川 祐真 210 メモリアロケータ ヒープ領域 0x0009 5000 0x0009 FFFF メモリ動的確保の要求があれば、 4KBずつ与える タスク管理 メモリ アロケータ 使用中の目印を 付けておこう heap_alloc_table という配列で管理
  211. 211. 2016/04/08 荒川 祐真 211 メモリアロケータ ヒープ領域 0x0009 5000 0x0009 FFFF メモリ動的確保の要求があれば、 4KBずつ与える タスク管理 メモリ アロケータ 確保できたよ 0x0009 5000
  212. 212. 2016/04/08 荒川 祐真 212 メモリアロケータ ヒープ領域 0x0009 5000 0x0009 FFFF メモリ動的確保の要求があれば、 4KBずつ与える タスク管理 メモリ アロケータ 0x0009 5000から 4KBの領域を uptimeのスタックに使おう
  213. 213. 2016/04/08 荒川 祐真 213 コード行数の推移 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数 【主な追加機能】 ● ファイルシステム ● メモリ管理 (メモリアロケータ) ● タスク管理 (タスクローダ)
  214. 214. 2016/04/08 荒川 祐真 214 カーネル 時間 管理 ファイルシステム システムコール デバイスドライバ アプリ shell uptime コンソール CPU メモリ KBC CRTCPIT :機能の呼び出し関係 タスク管理 スケジューラ タスクローダ メモリ管理 ページング メモリアロケータ ソ フ ト ハ ー ド OS5カーネルのアーキテクチャ
  215. 215. 2016/04/08 荒川 祐真 215 タスクローダとは ● 役割 1.ファイルシステム上からファイルを見つける 2.新たなタスクのためのメモリを確保 3.タスクの構造を用意し、初期化
  216. 216. 2016/04/08 荒川 祐真 216 タスクローダとは ● 役割 1.ファイルシステム上からファイルを見つける 2.新たなタスクのためのメモリを確保 3.タスクの構造を用意し、初期化 ファイルシステム
  217. 217. 2016/04/08 荒川 祐真 217 タスクローダとは ● 役割 1.ファイルシステム上からファイルを見つける 2.新たなタスクのためのメモリを確保 3.タスクの構造を用意し、初期化 ファイルシステム メモリ管理
  218. 218. 2016/04/08 荒川 祐真 218 タスクローダとは ● 役割 1.ファイルシステム上からファイルを見つける 2.新たなタスクのためのメモリを確保 3.タスクの構造を用意し、初期化 ファイルシステム メモリ管理 タスク管理
  219. 219. 2016/04/08 荒川 祐真 219 タスクローダとは ● 役割 1.ファイルシステム上からファイルを見つける 2.新たなタスクのためのメモリを確保 3.タスクの構造を用意し、初期化 ファイルシステム メモリ管理 タスク管理 カーネルの複数の機能の集大成
  220. 220. 2016/04/08 荒川 祐真 220 タスクの生成 ● タスクを生成する際は、 以下の領域のためのメモリを動的に確保し、 それぞれ初期化する – TSS – スタック領域 – ページディレクトリ・ページテーブル
  221. 221. 2016/04/08 荒川 祐真 221 タスクの初期化 os5/kernel/task.c の task_init 関数の動作を見てみる
  222. 222. 2016/04/08 荒川 祐真 222 タスクの初期化 ① 引数でstruct fileのポインタを受け取る struct listuptimeの struct file next prev char *name void *data_base_addr
  223. 223. 2016/04/08 荒川 祐真 223 タスクの初期化 ② タスク作成に必要なメモリを動的確保 struct listuptimeの struct file next prev char *name void *data_base_addr PD用 PT用 struct task用 スタック用
  224. 224. 2016/04/08 荒川 祐真 224 タスクの初期化 ③ タスク用PD・PTの初期化 struct listuptimeの struct file next prev char *name void *data_bas_addr struct task用 スタック用 カーネル ページ uptime ページ uptime用 PD uptime用 PT カーネル用 PT
  225. 225. 2016/04/08 荒川 祐真 225 タスクの初期化 ④ タスクIDを作成・設定 struct listuptimeの struct file next prev char *name void *data_base_addr struct task用 スタック用
  226. 226. 2016/04/08 荒川 祐真 226 タスクの初期化 ④ タスクIDを作成・設定 struct list uptimeの struct file next prev char *name void *data_base_addr struct task用 スタック用 struct task *prev struct task *next unsigned short task_id struct tss tss コンテキスト スイッチ用関数 スリープ用の メンバ uptimeの struct task
  227. 227. 2016/04/08 荒川 祐真 227 タスクの初期化 ④ タスクIDを作成・設定 struct list uptimeの struct file next prev char *name void *data_base_addr struct task用 スタック用 struct task *prev struct task *next unsigned short task_id struct tss tss コンテキスト スイッチ用関数 スリープ用の メンバ グローバル変数 task_id_counter をインクリメントし、 設定 ここでは2を設定したとする 2 uptimeの struct task
  228. 228. 2016/04/08 荒川 祐真 228 タスクの初期化 ⑤ コンテキストスイッチ用関数を作成・設定 struct list uptimeの struct file next prev char *name void *data_base_addr struct task用 スタック用 struct task *prev struct task *next unsigned short task_id struct tss tss コンテキスト スイッチ用関数 スリープ用の メンバ 2 uptimeの struct task
  229. 229. 2016/04/08 荒川 祐真 229 タスクの構造 タスクを管理する構造体: struct task
  230. 230. 2016/04/08 荒川 祐真 230 タスクの構造 タスクを管理する構造体: struct task void (*context_switch)(void); unsigned char context_switch_func[CONTEXT_SWITCH_FN_SIZE]
  231. 231. 2016/04/08 荒川 祐真 231 タスクの構造 タスクを管理する構造体: struct task void (*context_switch)(void); unsigned char context_switch_func[CONTEXT_SWITCH_FN_SIZE] ● 本来必要ないメンバ ● jmp命令でのコンテキストスイッチが オペランド即値指定でしか動作確認できていない ● 仕方なく、jmp命令の機械語をcharの配列に格納し、 タスク生成時、「生成したタスクへコンテキストスイッチする命令」へ 機械語を直接書き換えている jmp TSSのアドレス ここが即値指定の場合しか、 正常動作を確認できていない
  232. 232. 2016/04/08 荒川 祐真 232 タスクの初期化 ⑥ GDTの初期化(※説明割愛) struct list uptimeの struct file next prev char *name void *data_base_addr struct task用 スタック用 struct task *prev struct task *next unsigned short task_id struct tss tss コンテキスト スイッチ用関数 スリープ用の メンバ 2 uptimeの struct task
  233. 233. 2016/04/08 荒川 祐真 233 タスクの初期化 ⑦ TSS初期化 struct list uptimeの struct file next prev char *name void *data_base_addr struct task用 スタック用 struct task *prev struct task *next unsigned short task_id struct tss tss コンテキスト スイッチ用関数 スリープ用の メンバ 2 uptimeの struct task
  234. 234. 2016/04/08 荒川 祐真 234 タスクの初期化 ⑦ TSS初期化 struct list uptimeの struct file next prev char *name void *data_base_addr struct task用 スタック用 struct task *prev struct task *next unsigned short task_id struct tss tss コンテキスト スイッチ用関数 スリープ用の メンバ 2 ※ 一部 EIP CR3(PDBR) タスク用スタック カーネル用スタック
  235. 235. 2016/04/08 荒川 祐真 235 タスクの初期化 ⑦ TSS初期化 struct list uptimeの struct file next prev char *name void *data_base_addr struct task用 スタック用 struct task *prev struct task *next unsigned short task_id struct tss tss コンテキスト スイッチ用関数 スリープ用の メンバ 2 ※ 一部 EIP CR3(PDBR) タスク用スタック カーネル用スタック
  236. 236. 2016/04/08 荒川 祐真 236 タスクの初期化 ⑦ TSS初期化 struct list uptimeの struct file next prev char *name void *data_base_addr struct task用 スタック用 struct task *prev struct task *next unsigned short task_id struct tss tss コンテキスト スイッチ用関数 スリープ用の メンバ 2 ※ 一部 EIP CR3(PDBR) タスク用スタック カーネル用スタック
  237. 237. 2016/04/08 荒川 祐真 237 タスクの初期化 ⑦ TSS初期化 struct list uptimeの struct file next prev char *name void *data_base_addr struct task用 struct task *prev struct task *next unsigned short task_id struct tss tss コンテキスト スイッチ用関数 スリープ用の メンバ 2 ※ 一部 EIP CR3(PDBR) タスク用スタック カーネル用スタック スタック用
  238. 238. 2016/04/08 荒川 祐真 238 【再掲】OS5の現在のメモリマップ コンベンショナルメモリ 0x0000 0500 0x0009 FFFF カーネルスタック領域 (436.0KB) 0x0001 3000 〜 0x0007 FFFF 0x0008 0000カーネルスタックの ベースアドレス
  239. 239. 2016/04/08 荒川 祐真 239 タスクの初期化 ⑦ TSS初期化 struct list uptimeの struct file next prev char *name void *data_base_addr struct task用 struct task *prev struct task *next unsigned short task_id struct tss tss コンテキスト スイッチ用関数 スリープ用の メンバ 2 ※ 一部 EIP CR3(PDBR) タスク用スタック カーネル用スタック スタック用 0x0008 0000
  240. 240. 2016/04/08 荒川 祐真 240 タスクの初期化 ⑧ struct taskをランキューへ追加 struct task用 struct task *prev struct task *next unsigned short task_id struct tss tss コンテキスト スイッチ用関数 スリープ用の メンバ 2 スタック用 shell ランキュー 追加 uptimeの struct task
  241. 241. 2016/04/08 荒川 祐真 241 今日お話する内容 1.はじめに 2.OS5の概観 3.カーネル 4.おわりに
  242. 242. 2016/04/08 荒川 祐真 242 やはり昔の人は偉大 システムコール定数名 機能 TIMER_GET_GLOBAL_COUNTER 時間管理: グローバルカウンタ値取得 SCHED_WAKEUP_MSEC タスク管理(スケジューラ): ウェイクアップ時間を指定し、ス リープ CON_GET_CURSOR_POS_Y デバイスドライバ(コンソール): カーソル位置のY座標値取 得 CON_PUT_STR デバイスドライバ(コンソール): 文字列表示 CON_PUT_STR_POS デバイスドライバ(コンソール): 文字列表示(座標指定) CON_DUMP_HEX デバイスドライバ(コンソール): 指定した数値を16進数で表 示 CON_DUMP_HEX_POS デバイスドライバ(コンソール): 指定した数値を16進数で表 示(座標指定) CON_GET_LINE デバイスドライバ(コンソール): 1行の入力を取得 OPEN ファイルシステム: ファイルを開く EXEC ファイルシステム: ファイルを実行する
  243. 243. 2016/04/08 荒川 祐真 243 やはり昔の人は偉大 システムコール定数名 機能 TIMER_GET_GLOBAL_COUNTER 時間管理: グローバルカウンタ値取得 SCHED_WAKEUP_MSEC タスク管理(スケジューラ): ウェイクアップ時間を指定し、ス リープ CON_GET_CURSOR_POS_Y デバイスドライバ(コンソール): カーソル位置のY座標値取 得 CON_PUT_STR デバイスドライバ(コンソール): 文字列表示 CON_PUT_STR_POS デバイスドライバ(コンソール): 文字列表示(座標指定) CON_DUMP_HEX デバイスドライバ(コンソール): 指定した数値を16進数で表 示 CON_DUMP_HEX_POS デバイスドライバ(コンソール): 指定した数値を16進数で表 示(座標指定) CON_GET_LINE デバイスドライバ(コンソール): 1行の入力を取得 OPEN ファイルシステム: ファイルを開く EXEC ファイルシステム: ファイルを実行する ● 現在のOS5のシステムコールは粒度がまちまち <<現在のシステムコールの問題点>>
  244. 244. 2016/04/08 荒川 祐真 244 やはり昔の人は偉大 システムコール定数名 機能 TIMER_GET_GLOBAL_COUNTER 時間管理: グローバルカウンタ値取得 SCHED_WAKEUP_MSEC タスク管理(スケジューラ): ウェイクアップ時間を指定し、ス リープ CON_GET_CURSOR_POS_Y デバイスドライバ(コンソール): カーソル位置のY座標値取 得 CON_PUT_STR デバイスドライバ(コンソール): 文字列表示 CON_PUT_STR_POS デバイスドライバ(コンソール): 文字列表示(座標指定) CON_DUMP_HEX デバイスドライバ(コンソール): 指定した数値を16進数で表 示 CON_DUMP_HEX_POS デバイスドライバ(コンソール): 指定した数値を16進数で表 示(座標指定) CON_GET_LINE デバイスドライバ(コンソール): 1行の入力を取得 OPEN ファイルシステム: ファイルを開く EXEC ファイルシステム: ファイルを実行する ● 現在のOS5のシステムコールは粒度がまちまち ● 制御するデバイスの数だけシステムコールが必要になる <<現在のシステムコールの問題点>>
  245. 245. 2016/04/08 荒川 祐真 245 やはり昔の人は偉大 システムコール定数名 機能 TIMER_GET_GLOBAL_COUNTER 時間管理: グローバルカウンタ値取得 SCHED_WAKEUP_MSEC タスク管理(スケジューラ): ウェイクアップ時間を指定し、ス リープ CON_GET_CURSOR_POS_Y デバイスドライバ(コンソール): カーソル位置のY座標値取 得 CON_PUT_STR デバイスドライバ(コンソール): 文字列表示 CON_PUT_STR_POS デバイスドライバ(コンソール): 文字列表示(座標指定) CON_DUMP_HEX デバイスドライバ(コンソール): 指定した数値を16進数で表 示 CON_DUMP_HEX_POS デバイスドライバ(コンソール): 指定した数値を16進数で表 示(座標指定) CON_GET_LINE デバイスドライバ(コンソール): 1行の入力を取得 OPEN ファイルシステム: ファイルを開く EXEC ファイルシステム: ファイルを実行する ● 現在のOS5のシステムコールは粒度がまちまち ● 制御するデバイスの数だけシステムコールが必要になる ● UNIXの場合はデバイスもファイルとすることで、 open、read、write という共通のシステムコールで制御できるようにしている <<現在のシステムコールの問題点>>
  246. 246. 2016/04/08 荒川 祐真 246 やはり昔の人は偉大 システムコール定数名 機能 TIMER_GET_GLOBAL_COUNTER 時間管理: グローバルカウンタ値取得 SCHED_WAKEUP_MSEC タスク管理(スケジューラ): ウェイクアップ時間を指定し、ス リープ CON_GET_CURSOR_POS_Y デバイスドライバ(コンソール): カーソル位置のY座標値取 得 CON_PUT_STR デバイスドライバ(コンソール): 文字列表示 CON_PUT_STR_POS デバイスドライバ(コンソール): 文字列表示(座標指定) CON_DUMP_HEX デバイスドライバ(コンソール): 指定した数値を16進数で表 示 CON_DUMP_HEX_POS デバイスドライバ(コンソール): 指定した数値を16進数で表 示(座標指定) CON_GET_LINE デバイスドライバ(コンソール): 1行の入力を取得 OPEN ファイルシステム: ファイルを開く EXEC ファイルシステム: ファイルを実行する ● 現在のOS5のシステムコールは粒度がまちまち ● 制御するデバイスの数だけシステムコールが必要になる ● UNIXの場合はデバイスもファイルとすることで、 open、read、write という共通のシステムコールで制御できるようにしている → 「既存のものにただ合わせる」ということはしたく無く、   「ファイル」という概念すら新しい物に置き換えてみたかったが、   それ以上にシンプルにできるものが思いつかない・・・ <<現在のシステムコールの問題点>>
  247. 247. 2016/04/08 荒川 祐真 247 やはり昔の人は偉大 システムコール定数名 機能 TIMER_GET_GLOBAL_COUNTER 時間管理: グローバルカウンタ値取得 SCHED_WAKEUP_MSEC タスク管理(スケジューラ): ウェイクアップ時間を指定し、ス リープ CON_GET_CURSOR_POS_Y デバイスドライバ(コンソール): カーソル位置のY座標値取 得 CON_PUT_STR デバイスドライバ(コンソール): 文字列表示 CON_PUT_STR_POS デバイスドライバ(コンソール): 文字列表示(座標指定) CON_DUMP_HEX デバイスドライバ(コンソール): 指定した数値を16進数で表 示 CON_DUMP_HEX_POS デバイスドライバ(コンソール): 指定した数値を16進数で表 示(座標指定) CON_GET_LINE デバイスドライバ(コンソール): 1行の入力を取得 OPEN ファイルシステム: ファイルを開く EXEC ファイルシステム: ファイルを実行する ● 現在のOS5のシステムコールは粒度がまちまち ● 制御するデバイスの数だけシステムコールが必要になる ● UNIXの場合はデバイスもファイルとすることで、 open、read、write という共通のシステムコールで制御できるようにしている → 「既存のものにただ合わせる」ということはしたく無く、   「ファイル」という概念すら新しい物に置き換えてみたかったが、   それ以上にシンプルにできるものが思いつかない・・・   → UNIXを作った人は本当に頭が良いと思います。。 <<現在のシステムコールの問題点>>
  248. 248. 2016/04/08 荒川 祐真 248 やはり昔の人は偉大 システムコール定数名 機能 TIMER_GET_GLOBAL_COUNTER 時間管理: グローバルカウンタ値取得 SCHED_WAKEUP_MSEC タスク管理(スケジューラ): ウェイクアップ時間を指定し、ス リープ CON_GET_CURSOR_POS_Y デバイスドライバ(コンソール): カーソル位置のY座標値取 得 CON_PUT_STR デバイスドライバ(コンソール): 文字列表示 CON_PUT_STR_POS デバイスドライバ(コンソール): 文字列表示(座標指定) CON_DUMP_HEX デバイスドライバ(コンソール): 指定した数値を16進数で表 示 CON_DUMP_HEX_POS デバイスドライバ(コンソール): 指定した数値を16進数で表 示(座標指定) CON_GET_LINE デバイスドライバ(コンソール): 1行の入力を取得 OPEN ファイルシステム: ファイルを開く EXEC ファイルシステム: ファイルを実行する ● 現在のOS5のシステムコールは粒度がまちまち ● 制御するデバイスの数だけシステムコールが必要になる ● UNIXの場合はデバイスもファイルとすることで、 open、read、write という共通のシステムコールで制御できるようにしている → 「既存のものにただ合わせる」ということはしたく無く、   「ファイル」という概念すら新しい物に置き換えてみたかったが、   それ以上にシンプルにできるものが思いつかない・・・   → UNIXを作った人は本当に頭が良いと思います。。 <<現在のシステムコールの問題点>> 古きをたずねて、 先人の偉大さを知りました
  249. 249. 2016/04/08 荒川 祐真 249 ご清聴ありがとうございました
  250. 250. 2016/04/08 荒川 祐真 250 以降、付録です 時間の関係で割愛した説明や、 別の言い方での説明など 参考までに残しておきます
  251. 251. 2016/04/08 荒川 祐真 251 現状のブートローダーについて ● ハードウェアをセットアップし、 カーネルの先頭アドレスへジャンプする ● MBRの512バイトそのもの – 0x0000 7c00 〜 0x0000 7dff ● 現状は、全てアセンブラで記述
  252. 252. 2016/04/08 荒川 祐真 252 現状のブートローダーについて ● ハードウェアをセットアップし、 カーネルの先頭アドレスへジャンプする 少しブレークダウン 1. BIOS割り込みルーチンで ハードウェア初期化とRAMへのロード 2. CPUのモード変更 3. カーネルの先頭アドレスへジャンプ
  253. 253. 2016/04/08 荒川 祐真 253 現状のブートローダーについて ● ハードウェアをセットアップし、 カーネルの先頭アドレスへジャンプする 少しブレークダウン 1. BIOS割り込みルーチンで ハードウェア初期化とRAMへのロード 2. CPUのモード変更 3. カーネルの先頭アドレスへジャンプ
  254. 254. 2016/04/08 荒川 祐真 254 現状のブートローダーについて ● ハードウェアをセットアップし、 カーネルの先頭アドレスへジャンプする 少しブレークダウン 1. BIOS割り込みルーチンで ハードウェア初期化とRAMへのロード 2. CPUのモード変更 3. カーネルの先頭アドレスへジャンプ 【BIOS(Basic Input/Output System)】 ● ROMに書き込まれており、MBRをRAMにロードするなど、 MBRのプログラムが実行開始できるようにする ● そのため、FD・CD-ROM・HDDなどの読み書きや、 キー入力、モニター出力などの機能を備える ● 各機能はソフトウェア割り込みで呼び出せる (BIOS割り込みルーチン) – この機能により、FDドライバを自分で実装していなくて も、FDからデータをRAMにロードできる – ただし、利用できるのは16ビットモード(リアルモード)の み
  255. 255. 2016/04/08 荒川 祐真 255 現状のブートローダーについて ● ハードウェアをセットアップし、 カーネルの先頭アドレスへジャンプする 少しブレークダウン 1. BIOS割り込みルーチンで ハードウェア初期化とRAMへのロード 2. CPUのモード変更 3. カーネルの先頭アドレスへジャンプ
  256. 256. 2016/04/08 荒川 祐真 256 現状のブートローダーについて ● ハードウェアをセットアップし、 カーネルの先頭アドレスへジャンプする 少しブレークダウン 1. BIOS割り込みルーチンで ハードウェア初期化とRAMへのロード 2. CPUのモード変更 3. カーネルの先頭アドレスへジャンプ 16ビット → 32ビット
  257. 257. 2016/04/08 荒川 祐真 257 shellの動作の流れ はじめ おわり <SYSCALL_CON_PUT_STR> "OS5> "をコンソール表示 <SYSCALL_CON_GET_LINE> コンソール入力1行を取得 1行を半角スペース区切りの 最初の要素(command)と それ以降(args)に分割 commandは shell組み込みの コマンド? Yes No 組み込みコマンド 実行 <SYSCALL_OPEN> commandという ファイルを開く <SYSCALL_EXEC> 開いたファイルを 実行
  258. 258. 2016/04/08 荒川 祐真 258 uptimeの動作の流れ はじめ おわり <SYSCALL_TIMER_GET _GLOBAL_COUNTER> タイマーから経過ms取得 msを秒へ変換 <SYSCALL_CON_PUT _STR_POS> “uptime:”を座標値指定で コンソール表示 <SYSCALL_CON_GET _CURSOR_POS_Y> コンソールのカーソルの Y座標値取得 起動時間を表示する 座標計算 <SYSCALL_CON_DUMP _HEX_POS> タイマーの経過秒数を 座標指定で16進ダンプ <SYSCALL_SCHED _WAKEUP_MSEC> ウェイクアップタイマーを 33ms後に設定し、 スリープ
  259. 259. 2016/04/08 荒川 祐真 259 【補足】PIC(i8259A) PIC(Programmable Interrupt Controller) IC collection i8259 http://www.itofamily.com/ito/collections/peripherals/i8259/index.html ● ピンに接続されたハードウェアから割り込みを 受け付け、CPUへ伝える ● 割り込みはマスクできる ● 実際、PCのPICにはi8259Aが2つ使われている – マスターとスレーブ – スレーブの割り込み出力がマスターの割り込み入力に 接続されている
  260. 260. 2016/04/08 荒川 祐真 260 ページングとは? ● 仮想記憶(仮想メモリ)を実現する方式 ● メモリを「ページ」という単位で分割して管理する RAM アーキテクチャにもよるが、 OS5やLinux(x86)では4KB ページ
  261. 261. 2016/04/08 荒川 祐真 261 ページングとは? ● 複数のタスクを同時に実行する際、実行時に必要なページ のみロード RAM TaskA TaskB ページイン HDDなどの補助記憶 ページアウト
  262. 262. 2016/04/08 荒川 祐真 262 OS5でのページング ● とはいえ、OS5においてはカーネル・アプリ全 てメモリに乗るサイズ – ページイン・ページアウトも発生せず、実装もして いない ● ページングについては「仮想メモリ」の観点で 使用している
  263. 263. 2016/04/08 荒川 祐真 263 「変換表」について ● 実際には「ページディレクトリ(PD)」と 「ページテーブル(PT)」の2種類 ページテーブルページディレクトリ 表の各行は 「エントリ」 と呼ばれる ページディレクトリエントリ (PDE) ページテーブルエントリ (PTE)
  264. 264. 2016/04/08 荒川 祐真 264 「変換表」について ● 実際には「ページディレクトリ(PD)」と 「ページテーブル(PT)」の2種類 ページテーブルページディレクトリ ページディレクトリエントリは、 ページテーブルの先頭アドレスを指す
  265. 265. 2016/04/08 荒川 祐真 265 「変換表」について ページテーブルページディレクトリ ページ 4KB 4KB 4KB 4KB PTEが ページの先頭アドレスを指す
  266. 266. 2016/04/08 荒川 祐真 266 「変換表」について ページテーブルページディレクトリ ページ 4KB 4KB 4KB 4KB CR3 CPUのCR3というレジスタに PDの先頭アドレスが格納されている ※ 別名:PDBR(Page Directory Base Register)
  267. 267. 2016/04/08 荒川 祐真 267 「変換表」について ページテーブルページディレクトリ ページ 4KB 4KB 4KB 4KB CR3 VA→PAのアドレス変換は 階層構造
  268. 268. 2016/04/08 荒川 祐真 268 VAはオフセットの塊 ● PD・PT・ページ内のオフセットは どこで指定するのか?
  269. 269. 2016/04/08 荒川 祐真 269 VAはオフセットの塊 ● PD・PT・ページ内のオフセットは どこで指定するのか? 全てVAに含まれている
  270. 270. 2016/04/08 荒川 祐真 270 【補足】TLB ● PD・PTはメモリ上にあるため、 1度のメモリアクセスにつき、 PD・PTへのアクセスのために余分にメモリへ アクセスしなければならない ● アドレス変換高速化のため、 PDEとPTEをキャッシュするものとして TLB(トランスレーションルックアサイドバッファ)が 存在する ページングでは、アドレス変換にかかる時間がボトルネック
  271. 271. 2016/04/08 荒川 祐真 271 コード行数の推移 OS5の各機能は、以下のように実装されてきた 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08システムコールの他、 特権管理、省電力機能、 ロック機能 追加 日付(ブログ記事投稿) 総 コード 行数
  272. 272. 2016/04/08 荒川 祐真 272 OS5カーネルのアーキテクチャ カーネル 時間 管理 ファイルシステム システムコール デバイスドライバ アプリ shell uptime コンソール CPU メモリ KBC CRTCPIT :機能の呼び出し関係 タスク管理 スケジューラ タスクローダ メモリ管理 ページング メモリアロケータ ソ フ ト ハ ー ド 【ロック機能】 アプリケーションから 呼び出されるものではないが、 カーネルの基本機能の一つ
  273. 273. 2016/04/08 荒川 祐真 273 ロック機能 ● 役割 – 「ここだけは割り込んで欲しくない」・「他のタス クへ遷移して欲しくない」という区間でロックする ● やっていること – CPUのEFLAGSレジスタのIF(割り込みイネーブル フラグ)
  274. 274. 2016/04/08 荒川 祐真 274 ロック機能: 入れ子の場合の問題点 ● 入れ子にするとロックしたい区間にも関わら ず、ロックが解除されてしまう
  275. 275. 2016/04/08 荒川 祐真 275 ロック機能: 入れ子問題の対処 ● 実際には「単にレジスタの制御をするだけ」で はなく、ロック状態の退避・復帰を行っている
  276. 276. 2016/04/08 荒川 祐真 276 システムコール: open struct listshellの struct file next prev char *name void *data_bas_addr 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 shell uptimestruct listuptimeの struct file next prev char *name void *data_bas_addr 【前提】 ● システムコールopenは、 引数でファイル名の文字列の ポインタを受け取る ● 今回は、"uptime”を受け取った とする
  277. 277. 2016/04/08 荒川 祐真 277 システムコール: open struct listshellの struct file next prev char *name void *data_bas_addr 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 shell uptimestruct listuptimeの struct file next prev char *name void *data_bas_addr ①リンクリストの先頭から、 “uptime”に一致する nameを持つものを探す
  278. 278. 2016/04/08 荒川 祐真 278 システムコール: open struct listshellの struct file next prev char *name void *data_bas_addr 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 shell uptimestruct listuptimeの struct file next prev char *name void *data_bas_addr ②見つけた
  279. 279. 2016/04/08 荒川 祐真 279 システムコール: open struct listshellの struct file next prev char *name void *data_bas_addr 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 shell uptimestruct listuptimeの struct file next prev char *name void *data_bas_addr ③struct fileの 先頭アドレスを返す
  280. 280. 2016/04/08 荒川 祐真 280 システムコール: exec ● システムコールexecはタスク管理の機能 ● 引数でstruct fileのポインタを受け取る ● 内部的には単にタスク管理のtask_init関数を呼 び出すだけ – task_init関数はstruct fileのポインタを引数とする
  281. 281. 2016/04/08 荒川 祐真 281 失敗談: ltr命令でリブート ● 現象 – ltr命令によりタスクレジスタへロードさせる と、QEMU上でリブートしてしまう ● 原因/解決方法 – GDTの4つ目にTSSのディスクリプタを配置してい たが、lgdtでGDTの範囲がディスクリプタ3つ分の ままだった
  282. 282. 2016/04/08 荒川 祐真 282 失敗談: コンテキストスイッチの ljmp実行でリブートを繰り返す ● 現象 – コンテキストスイッチのljmp実行でリブートを繰り 返す ● 原因/解決方法 – shellのTSSのCR3が初期化されていなかったことが 問題であった
  283. 283. 2016/04/08 荒川 祐真 283 失敗談: キー入力時、ゴミが入る ● 現象 – キー入力時、ゴミが入る ● 原因/解決方法 – デキューとエラーステータス確認の間に、キーボー ド割り込みからのエンキューが入り、エラーステー タスが上書きされてしまっていたことが原因であっ た
  284. 284. 2016/04/08 荒川 祐真 284 失敗談: 作成したPTEを使用すると ブート・リブートを繰り返す ● 現象 – 作成したPTEを使用するとブート・リブートを繰り 返す – uptimeを無効化(タイマ割り込み無効化)で発生しな くなる ● 原因/解決方法 – PD初期化を間違っていた
  285. 285. 2016/04/08 荒川 祐真 285 失敗談: 文字列リテラルへのアクセ ス時にNull pointer dereference ● 現象 – 文字列リテラルへのアクセス時にNull pointer dereference ● 原因/解決方法 – shellの0x20000000のcall時、それはshell_startではな く、command_echoだった ● shell_startはtextセクション内一番末尾の関数 – 問題発生の流れ 1.command_echoは引数にchar *を取るが、0x20000000のcall時、引数を渡してい ないので、command_echoはその時スタックに積まれていた0をchar *と解釈し てそこへアクセス 2.0x00000000はマップされていないのでPF
  286. 286. 2016/04/08 荒川 祐真 286 失敗談: スタック動的確保対応 task_initでshellのreadl 20000000で リブートする問題 ● ページのベースアドレスを登録すべきphys_stack_baseに、勘違いしてスタックのベースアドレス(4KBページの末尾のアドレス)を登録 していたことが原因 ● この場合、以下の事態になる | mem_alloc | | ● | 割り当て番目 | 用途 | ● |--------------+-----------------------------------------------| ● | 1 | shell: pd_base_addr | ● | 2 | shell: pt_base_addr | ● | 3 | shell: new_task | ● | 4 | | ● | 5 | shell: phys_stack_base : uptime: pd_base_addr | ● | 6 | uptime: pt_base_addr | ● | 7 | uptime: new_task | ● | 8 | | ● | 9 | uptime: phys_stack_base | ● | 10 | | ● | 11 | | ● shellのphys_stack_baseがuptimeのpd_base_addrと被っており、shellのスタックがアドレス末尾から上がっていって、uptimeのPDの領 域を壊した時リブート

×