Successfully reported this slideshow.
Your SlideShare is downloading. ×

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

More Related Content

Related Books

Free with a 30 day trial from Scribd

See all

【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の領 域を壊した時リブート

×