SlideShare a Scribd company logo
【2000行弱!】x86用自作カーネルの紹介
荒川 祐真
2016/04/08
2016/04/08 荒川 祐真 2
自己紹介
●
名前: 荒川 祐真  →  大神 祐真
●
仕事: 組み込み系のプログラマ
●
趣味: アーケードゲーム(古いシューティング系)、
   OS自作(OS5)
●
最近よく使う言語(よく使うものから順に)
– C言語、シェルスクリプト(言語?)、アセンブラ(x86)
2016/04/08 荒川 祐真 3
自己紹介
●
名前: 荒川 祐真  →  大神 祐真
●
仕事: 組み込み系のプログラマ
●
趣味: アーケードゲーム(古いシューティング系)、
   OS自作(OS5)
●
最近よく使う言語(よく使うものから順に)
– C言語、シェルスクリプト(言語?)、アセンブラ(x86)
本日の勉強会で
紹介
2016/04/08 荒川 祐真 4
今日お話する内容
1.はじめに
2.OS5の概観
3.カーネル
4.おわりに
2016/04/08 荒川 祐真 5
今日お話する内容
1.はじめに
2.OS5の概観
3.カーネル
4.おわりに
時間管理、タスク管理、
メモリ管理、ファイルシステム、
システムコール
各機能が
どのように実装されてきたかを
見ていきます
2016/04/08 荒川 祐真 6
今日お話する内容
1.はじめに
2.OS5の概観
3.カーネル
4.おわりに
2016/04/08 荒川 祐真 7
OS5とは
●
フルスクラッチ
– OSについて理解したことの確認
2016/04/08 荒川 祐真 8
OS5とは
●
フルスクラッチ
– OSについて理解したことの確認
良くも悪くも、
オリジナルなOS
2016/04/08 荒川 祐真 9
OS5とは
●
フルスクラッチ
– OSについて理解したことの確認
●
まずはシンプルに
– OS5の各機能(後述)は、
「そのとき必要な最小限」で実装
良くも悪くも、
オリジナルなOS
2016/04/08 荒川 祐真 10
今日お話する内容
1.はじめに
2.OS5の概観
3.カーネル
4.おわりに
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
2016/04/08 荒川 祐真 12
OS5でできること
●
OS5はQEMU上で動作
●
MakeとGCCがあれば、
x86(32bit)マシン上でビルド可能
– x86(64bit)環境用には、
ビルド環境をQEMUイメージで公開中
OS5に関する情報は以下にまとめています
http://funlinux.org/os5/
2016/04/08 荒川 祐真 13
コード行数の推移
2015/04/05
2015/08/24
2015/10/31
2015/11/30
2016/02/08
日付(ブログ記事投稿)
総
コード
行数
2016/04/08 荒川 祐真 14
コード行数の推移
2015/04/05
2015/08/24
2015/10/31
2015/11/30
2016/02/08
日付(ブログ記事投稿)
総
コード
行数
ブートローダー・カーネル・アプリ
の総コード行数
2016/04/08 荒川 祐真 15
コード行数の推移
2015/04/05
2015/08/24
2015/10/31
2015/11/30
2016/02/08
日付(ブログ記事投稿)
総
コード
行数
ブートローダー : 253行
カーネル : 1966行
アプリケーション: 437行
2016/04/08 荒川 祐真 16
コード行数の推移
2015/04/05
2015/08/24
2015/10/31
2015/11/30
2016/02/08
日付(ブログ記事投稿)
総
コード
行数
ブートローダー : 253行
カーネル : 1966行
アプリケーション: 437行
2016/04/08 荒川 祐真 17
OS5カーネルのアーキテクチャ
カーネル
時間
管理
ファイルシステム
システムコール
デバイスドライバ
アプリ shell uptime
コンソール
CPU メモリ KBC CRTCPIT
:機能の呼び出し関係
タスク管理
スケジューラ
タスクローダ
メモリ管理
ページング
メモリアロケータ
ソ
フ
ト
ハ
ー
ド
2016/04/08 荒川 祐真 18
ブートローダーの概要
今回の主題はカーネルだが、
カーネルが起動するまでの流れとして
ブートローダーを簡単に紹介
2016/04/08 荒川 祐真 19
ブートローダーの概要
PC
電源
ON
2016/04/08 荒川 祐真 20
ブートローダーの概要
PC
電源
ON
BIOS
2016/04/08 荒川 祐真 21
ブートローダーの概要
PC
電源
ON
BIOS
● Basic Input/Output System
● 起動デバイスのMBR(Master Boot Record、先頭512バイト)
をRAMにロードし、CPUに実行させる
2016/04/08 荒川 祐真 22
ブートローダーの概要
PC
電源
ON
BIOS ブート
ローダー
● 512バイトに収まっており、MBR自体に相当
●
以下を行う
1. モニターの画面モード設定
2. カーネルとアプリのバイナリをRAMへロード
3. CPUモードを16ビットから32ビットへ移行
4. RAMへロードしたカーネルを実行
※ 1と2はBIOSの機能を利用する
2016/04/08 荒川 祐真 23
今日お話する内容
1.はじめに
2.OS5の概観
3.カーネル
4.おわりに
2016/04/08 荒川 祐真 24
コード行数の推移
2015/04/05
2015/08/24
2015/10/31
2015/11/30
2016/02/08
日付(ブログ記事投稿)
総
コード
行数
2016/04/08 荒川 祐真 25
コード行数の推移
2015/04/05
2015/08/24
2015/10/31
2015/11/30
2016/02/08
日付(ブログ記事投稿)
総
コード
行数
【主な追加機能】
●
ブートローダー
● アプリ(shell)
● デバイスドライバ(コンソール)
2016/04/08 荒川 祐真 26
コード行数の推移
2015/04/05
2015/08/24
2015/10/31
2015/11/30
2016/02/08
日付(ブログ記事投稿)
総
コード
行数
【主な追加機能】
●
ブートローダー
● アプリ(shell)
● デバイスドライバ(コンソール)
2016/04/08 荒川 祐真 27
OS5カーネルのアーキテクチャ
デバイスドライバ
shell
コンソール
CPU メモリ KBC CRTCPIT
:機能の呼び出し関係
ソ
フ
ト
ハ
ー
ド
2016/04/08 荒川 祐真 28
デバイスドライバとは
●
ハードウェアを抽象化して、
利用しやすくする
●
現状のOS5カーネルでは、
「KBC(キーボードコントローラ)」と
「CRTC(CRTコントローラ)」を
「コンソール」として抽象化している
デバイスドライバ
コンソール
KBC CRTC
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の姿を見てみると面白いです
2016/04/08 荒川 祐真 30
KBC i8042について
●
キーボードやマウスを管理するための
ワンチップ・マイコン
●
キーボードやマウスにもワンチップ・マイコン
が搭載されており、それらと相互に通信する
2016/04/08 荒川 祐真 31
制御用ICの使い方
●
in/out 命令を使用
●
書式
– in ICの読み出すレジスタのアドレス, CPUの汎用レジスタ名
– out CPUの汎用レジスタ名, ICの書き込むレジスタのアドレス
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
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
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
2016/04/08 荒川 祐真 35
CRTC(MC6845)の使い方
1. ブートローダーで画面モードを設定
➔ BIOSの機能を活用
2. カーネル起動後はVRAM領域への
 データ書き込みで画面描画される
➔ VRAM領域: 0x000B 8000 〜 0x000B FFFF
2016/04/08 荒川 祐真 36
関連するソースコード
● os5/kernel/console_io.c
● os5/kernel/include/console_io.h
2016/04/08 荒川 祐真 37
コード行数の推移
2015/04/05
2015/08/24
2015/10/31
2015/11/30
2016/02/08
日付(ブログ記事投稿)
総
コード
行数
【主な追加機能】
●
時間管理
●
タスク管理
(スケジューラによる
マルチタスク)
● アプリ(uptime)
2016/04/08 荒川 祐真 38
コード行数の推移
2015/04/05
2015/08/24
2015/10/31
2015/11/30
2016/02/08
日付(ブログ記事投稿)
総
コード
行数
【主な追加機能】
●
時間管理
●
タスク管理
(スケジューラによる
マルチタスク)
● アプリ(uptime)
2016/04/08 荒川 祐真 39
OS5カーネルのアーキテクチャ
時間
管理
デバイスドライバ
shell
コンソール
CPU メモリ KBC CRTCPIT
:機能の呼び出し関係
ソ
フ
ト
ハ
ー
ド
2016/04/08 荒川 祐真 40
時間管理について
●
役割
– 時間という単位の生成・管理・提供
●
やっていること
– タイマー割り込み毎(10ms)に
グローバルなカウンタ用変数をインクリメント
●
使用するハードウェア
– PIT(Programmable Interval Timer)
PIT
2016/04/08 荒川 祐真 41
使用するハードウェアについて
PIT(i8253あるいはi8254)
●
16bit長のカウンタを3ch内蔵
●
カウント動作をバイナリ/BCDで設定
●
6種類の動作モード
IC collection i8253,i8254
http://www.itofamily.com/ito/collections/peripherals/i8253-54/
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桁として扱う
2016/04/08 荒川 祐真 43
使用するハードウェアについて
PIT(i8253あるいはi8254)
●
16bit長のカウンタを3ch内蔵
●
カウント動作をバイナリ/BCDで設定
●
6種類の動作モード
IC collection i8253,i8254
http://www.itofamily.com/ito/collections/peripherals/i8253-54/
2016/04/08 荒川 祐真 44
PITの動作モード
OS5カーネルではモード2に設定
0から作るOS開発 割り込みその3 PICのまとめとPITと割り込みハンドラ
http://softwaretechnique.jp/OS_Development/kernel_development04.html
カウンタ
割り込み
0x0000
2016/04/08 荒川 祐真 45
PITの動作モード
OS5カーネルではモード2に設定
0から作るOS開発 割り込みその3 PICのまとめとPITと割り込みハンドラ
http://softwaretechnique.jp/OS_Development/kernel_development04.html
カウンタ
割り込み
0x2E9C
カウンタに
値をセット
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
2016/04/08 荒川 祐真 47
PITの動作モード
OS5カーネルではモード2に設定
0から作るOS開発 割り込みその3 PICのまとめとPITと割り込みハンドラ
http://softwaretechnique.jp/OS_Development/kernel_development04.html
カウンタ
割り込み
0x2E9C
0x0000
2016/04/08 荒川 祐真 48
PITの動作モード
OS5カーネルではモード2に設定
0から作るOS開発 割り込みその3 PICのまとめとPITと割り込みハンドラ
http://softwaretechnique.jp/OS_Development/kernel_development04.html
カウンタ
割り込み
0x2E9C
0x0000
タイマー
割り込み
2016/04/08 荒川 祐真 49
PITの動作モード
OS5カーネルではモード2に設定
0から作るOS開発 割り込みその3 PICのまとめとPITと割り込みハンドラ
http://softwaretechnique.jp/OS_Development/kernel_development04.html
カウンタ
割り込み
0x2E9C
0x0000
モード2だと、2回目以降は
自動でセットされる
2016/04/08 荒川 祐真 50
PITの動作モード
OS5カーネルではモード2に設定
0から作るOS開発 割り込みその3 PICのまとめとPITと割り込みハンドラ
http://softwaretechnique.jp/OS_Development/kernel_development04.html
カウンタ
割り込み
0x2E9C
0x0000
2016/04/08 荒川 祐真 51
PITの動作モード
OS5カーネルではモード2に設定
0から作るOS開発 割り込みその3 PICのまとめとPITと割り込みハンドラ
http://softwaretechnique.jp/OS_Development/kernel_development04.html
カウンタ
割り込み
0x2E9C
0x0000
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
2016/04/08 荒川 祐真 53
実装
●
ソースコード
– os5/kernel/timer.c
– os5/kernel/include/timer.h
2016/04/08 荒川 祐真 54
コード行数の推移
2015/04/05
2015/08/24
2015/10/31
2015/11/30
2016/02/08
日付(ブログ記事投稿)
総
コード
行数
【主な追加機能】
●
時間管理
●
タスク管理
(スケジューラによる
マルチタスク)
● アプリ(uptime)
2016/04/08 荒川 祐真 55
OS5カーネルのアーキテクチャ
カーネル
時間
管理
デバイスドライバ
アプリ shell uptime
コンソール
CPU メモリ KBC CRTCPIT
:機能の呼び出し関係
タスク管理
スケジューラ
ソ
フ
ト
ハ
ー
ド
2016/04/08 荒川 祐真 56
タスクとは?
●
OS5のカーネル上で実行される処理の単位
●
現状は、shellとuptimeの2つ
●
現状、タスク=アプリケーション
– カーネル内のタスク管理で話をするときはタスク
– カーネルより上位で話をするときはアプリケーション
2016/04/08 荒川 祐真 57
タスクの構造
タスクを管理する構造体: struct task
os5/kernel/include/task.h
2016/04/08 荒川 祐真 58
タスクの構造
タスクを管理する構造体: struct task
os5/kernel/include/task.h
2016/04/08 荒川 祐真 59
タスクの構造
タスクを管理する構造体: struct task
os5/kernel/include/task.h
実行可能タスクを管理する
双方向リスト
(ランキュー)
2016/04/08 荒川 祐真 60
タスクの構造
タスクを管理する構造体: struct task
os5/kernel/include/task.h
タスクを一意に決める
ID
2016/04/08 荒川 祐真 61
タスクの構造
タスクを管理する構造体: struct task
以降のメンバは、
後ほど、登場する際に紹介
2016/04/08 荒川 祐真 62
マルチタスク
複数のタスクをちょっとずつ、
切り替えながら実行
shell
uptime
shell
uptime
shell
uptime
時間
2016/04/08 荒川 祐真 63
マルチタスク
複数のタスクをちょっとずつ、
切り替えながら実行
shell
uptime
shell
uptime
shell
uptime
タイマー割り込み
タイマー割り込み
タイマー割り込み
タイマー割り込み
タイマー割り込み
タイマー割り込み
タイマー割り込み
10ms
時間
2016/04/08 荒川 祐真 64
マルチタスク
複数のタスクをちょっとずつ、
切り替えながら実行
shell
uptime
shell
uptime
shell
uptime
タイマー割り込み
タイマー割り込み
タイマー割り込み
タイマー割り込み
タイマー割り込み
タイマー割り込み
タイマー割り込み
10ms
時間
「タイムスライス」
と呼ぶ
2016/04/08 荒川 祐真 65
マルチタスク
複数のタスクをちょっとずつ、
切り替えながら実行
shell
uptime
shell
uptime
shell
uptime
タイマー割り込み
タイマー割り込み
タイマー割り込み
タイマー割り込み
タイマー割り込み
タイマー割り込み
タイマー割り込み
10ms
スケジューラは
いわば、
CPUの計算資源の
管理
時間
2016/04/08 荒川 祐真 66
マルチタスク
複数のタスクをちょっとずつ、
切り替えながら実行
shell
uptime
shell
uptime
shell
uptime
タイマー割り込み
タイマー割り込み
タイマー割り込み
タイマー割り込み
タイマー割り込み
タイマー割り込み
タイマー割り込み
10ms
スケジューラは
いわば、
CPUの計算資源の
管理
時間
「コンテキストスイッチ」
と呼ぶ
2016/04/08 荒川 祐真 67
コンテキストスイッチの流れ
shell
uptime
現在
実行中の
タスク
ランキュー
struct task
2016/04/08 荒川 祐真 68
コンテキストスイッチの流れ
shell
uptime
現在
実行中の
タスク
ランキュー
コンテキストスイッチ
イベント
発生
2016/04/08 荒川 祐真 69
コンテキストスイッチの流れ
shell
uptime
現在
実行中の
タスク
ランキュー
タスク管理
スケジューラ
スケジューラは
次に実行するタスクを
選択
次に
実行する
タスク
2016/04/08 荒川 祐真 70
コンテキストスイッチの流れ
shell
uptime
現在
実行中の
タスク
ランキュー
タスク管理
スケジューラ
次に
実行する
タスク
コンテキストスイッチ
2016/04/08 荒川 祐真 71
コンテキストスイッチに必要なこと
今までshellを実行していたCPUを
uptimeへスイッチするには
1.shellを再開するときのために、
情報を退避
2.退避していたuptimeの情報を
復帰
3.uptimeを再開
2016/04/08 荒川 祐真 72
コンテキストスイッチに必要なこと
今までshellを実行していたCPUを
uptimeへスイッチするには
1.shellを再開するときのために、
情報を退避
2.退避していたuptimeの情報を
復帰
3.uptimeを再開
このような情報をコンテキストと呼ぶ
コンテキストに含まれるもの
● IP(インストラクションポインタ)
●
フラグレジスタ
●
スタックポインタ
●
汎用レジスタ
2016/04/08 荒川 祐真 73
コンテキストスイッチに必要なこと
今までshellを実行していたCPUを
uptimeへスイッチするには
1.shellを再開するときのために、
情報を退避
2.退避していたuptimeの情報を
復帰
3.uptimeを再開
2016/04/08 荒川 祐真 74
コンテキストスイッチに必要なこと
今までshellを実行していたCPUを
uptimeへスイッチするには
1.shellを再開するときのために、
情報を退避
2.退避していたuptimeの情報を
復帰
3.uptimeを再開
x86 CPUの
タスク機能を
活用
2016/04/08 荒川 祐真 75
x86のタスク機能
●
x86のCPUはタスクを管理する構造と機能を
持っている
●
やってくれること
– 命令1つで
1. 実行中タスクの退避
2. 次に実行するタスクの復帰
3. 実行再開
を行ってくれる
2016/04/08 荒川 祐真 76
x86のタスク機能
●
x86のCPUはタスクを管理する構造と機能を
持っている
●
やってくれること
– 命令1つで
1. 実行中タスクの退避
2. 次に実行するタスクの復帰
3. 実行再開
を行ってくれる
jmp TSSのアドレス
2016/04/08 荒川 祐真 77
x86のタスク機能
●
x86のCPUはタスクを管理する構造と機能を
持っている
●
やってくれること
– 命令1つで
1. 実行中タスクの退避
2. 次に実行するタスクの復帰
3. 実行再開
を行ってくれる
jmp TSSのアドレス
【TSS】
Task State Segment
タスクの退避/復帰で
使用する領域
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
こんな形をしています
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
2016/04/08 荒川 祐真 80
タスクの構造
タスクを管理する構造体: struct task
2016/04/08 荒川 祐真 81
関連するソースコード
●
スケジューラ
– os5/kernel/sched.c
– os5/kernel/include/sched.h
●
タスク
– os5/kernel/task.c
– os5/kernel/include/task.h
2016/04/08 荒川 祐真 82
コード行数の推移
2015/04/05
2015/08/24
2015/10/31
2015/11/30
2016/02/08
日付(ブログ記事投稿)
総
コード
行数
【主な追加機能】
●
メモリ管理
(ページング)
2016/04/08 荒川 祐真 83
コード行数の推移
2015/04/05
2015/08/24
2015/10/31
2015/11/30
2016/02/08
日付(ブログ記事投稿)
総
コード
行数
【主な追加機能】
●
メモリ管理
(ページング)
2016/04/08 荒川 祐真 84
カーネル
時間
管理
デバイスドライバ
アプリ shell uptime
コンソール
CPU メモリ KBC CRTCPIT
:機能の呼び出し関係
タスク管理
スケジューラ
メモリ管理
ページング
ソ
フ
ト
ハ
ー
ド
OS5カーネルのアーキテクチャ
2016/04/08 荒川 祐真 85
OS5の現在のメモリマップ
物理アドレス空間 0x0000 0000
0xFFFF FFFF
2016/04/08 荒川 祐真 86
OS5の現在のメモリマップ
物理アドレス空間 0x0000 0000
0xFFFF FFFF
2016/04/08 荒川 祐真 87
OS5の現在のメモリマップ
物理アドレス空間 0x0000 0000
0xFFFF FFFF
コンベンショナルメモリ領域
(640KB)
0x0000 0500 〜 0x0009 FFFF
2016/04/08 荒川 祐真 88
OS5の現在のメモリマップ
コンベンショナルメモリ 0x0000 0500
0x0009 FFFF
OS5は現在、
このコンベンショナルメモリの領域
を想定し、動作している
2016/04/08 荒川 祐真 89
OS5の現在のメモリマップ
コンベンショナルメモリ 0x0000 0500
0x0009 FFFF
カーネルバイナリ配置領域
(36.5KB)
0x0000 7E00 〜 0x0001 0FFF
ユーザーランド配置領域
(12.0KB)
0x0001 1000 〜 0x0001 3FFF
2016/04/08 荒川 祐真 90
OS5の現在のメモリマップ
コンベンショナルメモリ 0x0000 0500
0x0009 FFFF
カーネルバイナリ配置領域
(36.5KB)
0x0000 7E00 〜 0x0001 0FFF
ユーザーランド配置領域
(12.0KB)
0x0001 1000 〜 0x0001 3FFF
カーネルやブートローダーを
配置する領域とは別の領域
ファイルシステムを用意し、
ファイルを配置する
現状は、shellとuptimeの
実行ファイルのみ
2016/04/08 荒川 祐真 91
OS5の現在のメモリマップ
コンベンショナルメモリ 0x0000 0500
0x0009 FFFF
カーネルスタック領域
(436.0KB)
0x0001 3000 〜 0x0007 FFFF
カーネル用ページテーブル配置領域
(8.0KB)
0x0008 F000 〜 0x0009 0FFF
0x0008 0000
2016/04/08 荒川 祐真 92
OS5の現在のメモリマップ
コンベンショナルメモリ 0x0000 0500
0x0009 FFFF
ヒープ領域
(44.0KB)
0x0009 5000 〜 0x0009 FFFF
0x0008 0000
2016/04/08 荒川 祐真 93
ページングとは?
物理アドレス空間を固定長(4KB)毎に分割
それぞれに、物理アドレスとは別のアドレス
(仮想アドレス)を割り当て、
メモリを管理する仕組み
2016/04/08 荒川 祐真 94
ページングとは?
物理アドレス空間
※ 表示の都合上、
  コンベンショナルメモリ領域を
  拡大
0x0000 0500
0x0009 FFFF
0x0008 0000
2016/04/08 荒川 祐真 95
ページングとは?
物理アドレス空間
※ 表示の都合上、
  コンベンショナルメモリ領域を
  拡大
0x0000 0500
0x0009 FFFF
0x0008 0000
ユーザーランド配置領域
(12.0KB)
0x0001 1000 〜 0x0001 3FFF
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
2016/04/08 荒川 祐真 97
ページングとは?
物理アドレス空間
※ 表示の都合上、
  ユーザーランド領域を
  拡大
0x0001 1000
0x0001 3FFF
0x0001 2000
0x0001 3000
物理アドレス空間全体
(0x0000 0000 〜 0xFFFF FFFF)を、
4KB単位で分割
分割した
各4KBの領域を
「ページ」と呼ぶ
2016/04/08 荒川 祐真 98
ページングとは?
物理アドレス空間
※ 表示の都合上、
  ユーザーランド領域を
  拡大
0x0001 1000
0x0001 3FFF
0x0001 2000
0x0001 3000
仮想アドレス(VA)を
物理アドレス(PA)へ変換する
変換表を用意
VA PA
0x2000 0000 0x0001 2000
2016/04/08 荒川 祐真 99
ページングとは?
物理アドレス空間
※ 表示の都合上、
  ユーザーランド領域を
  拡大
0x0001 1000
0x0001 3FFF
0x0001 2000
0x0001 3000
仮想アドレス(VA)を
物理アドレス(PA)へ変換する
変換表を用意
VA PA
0x2000 0000 0x0001 2000
※ ちなみに、VAにPAを対応付けることを、
  「マップする」と言う
2016/04/08 荒川 祐真 100
ページングとは?
物理アドレス空間
※ 表示の都合上、
  ユーザーランド領域を
  拡大
0x0001 1000
0x0001 3FFF
0x0001 2000
0x0001 3000
ページング有効化!
VA PA
0x2000 0000 0x0001 2000
MMU
【Memory Management Unit】
アドレス変換を行ってくれる
ハードウェア
2016/04/08 荒川 祐真 101
ページングとは?
物理アドレス空間
※ 表示の都合上、
  ユーザーランド領域を
  拡大
0x0001 1000
0x0001 3FFF
0x0001 2000
0x0001 3000
CPUはMMUを介して
メモリアクセス
VA PA
0x2000 0000 0x0001 2000
MMU
2016/04/08 荒川 祐真 102
ページングとは?
物理アドレス空間
※ 表示の都合上、
  ユーザーランド領域を
  拡大
0x0001 1000
0x0001 3FFF
0x0001 2000
0x0001 3000
=
MMUは
CPUがアクセスするアドレス(VA)を
PAに変換
VA PA
0x2000 0000 0x0001 2000
MMU
2016/04/08 荒川 祐真 103
ページングとは?
物理アドレス空間
※ 表示の都合上、
  ユーザーランド領域を
  拡大
0x0001 1000
0x0001 3FFF
=
0x0001 2000
0x0001 3000
MMUは
CPUがアクセスするアドレス(VA)を
PAに変換
VA PA
0x2000 0000 0x0001 2000
MMU
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用
2016/04/08 荒川 祐真 105
仮想アドレス空間のメモリマップ
0x0000 0000
0xFFFF FFFF
カーネル
空間
ユーザ
空間
0x2000 0000
仮
想
ア
ド
レ
ス
空
間
コンベンショナル
メモリ領域
物
理
ア
ド
レ
ス
空
間
2016/04/08 荒川 祐真 106
仮想アドレス空間のメモリマップ
0x0000 0000
0xFFFF FFFF
カーネル
空間
ユーザ
空間
0x2000 0000
仮
想
ア
ド
レ
ス
空
間
コンベンショナル
メモリ領域
物
理
ア
ド
レ
ス
空
間
VA=PA
カーネル空間から
全ての資源にアクセス可
2016/04/08 荒川 祐真 107
仮想アドレス空間のメモリマップ
0x0000 0000
0xFFFF FFFF
カーネル
空間
ユーザ
空間
0x2000 0000
仮
想
ア
ド
レ
ス
空
間
物
理
ア
ド
レ
ス
空
間
shell
uptime
VAは
現在実行中のタスクに
マップされる
(この場合shell)
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のこと
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
2016/04/08 荒川 祐真 110
shellとuptimeのPD・PTについて
ページテーブルページディレクトリ ページ
カーネル
shell
uptime
shell用
uptime用 shell用
uptime用
カーネル用
2016/04/08 荒川 祐真 111
shellとuptimeのPD・PTについて
ページテーブルページディレクトリ ページ
カーネル
shell
uptime
shell用
uptime用 shell用
uptime用
カーネル用
共通のPTを使用
2016/04/08 荒川 祐真 112
shellとuptimeのPD・PTについて
ページテーブルページディレクトリ ページ
カーネル
shell
uptime
shell用
uptime用 shell用
uptime用
カーネル用
タスク毎のPD切り替えも
コンテキストスイッチ時に
CPUが自動で行う
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は
タスク生成時に
動的確保
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
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
2016/04/08 荒川 祐真 116
関連するソースコード
● os5/kernel/memory.c
● os5/kernel/include/memory.h
2016/04/08 荒川 祐真 117
OS5の機能構成(ソースコード構成)
2015/04/05
2015/08/24
2015/10/31
2015/11/30
2016/02/08
日付(ブログ記事投稿)
総
コード
行数
【主な追加機能】
●
タスク管理
(スケジューラによる
タスクスリープ/ウェイクアップ)
●
省電力機能
●
特権管理
●
システムコール
2016/04/08 荒川 祐真 118
OS5の機能構成(ソースコード構成)
2015/04/05
2015/08/24
2015/10/31
2015/11/30
2016/02/08
日付(ブログ記事投稿)
総
コード
行数
【主な追加機能】
●
タスク管理
(スケジューラによる
タスクスリープ/ウェイクアップ)
●
省電力機能
●
特権管理
●
システムコール
2016/04/08 荒川 祐真 119
カーネル
時間
管理
デバイスドライバ
アプリ shell uptime
コンソール
CPU メモリ KBC CRTCPIT
:機能の呼び出し関係
タスク管理
スケジューラ
メモリ管理
ページング
ソ
フ
ト
ハ
ー
ド
OS5カーネルのアーキテクチャ
2016/04/08 荒川 祐真 120
タスクのスリープについて
●
タスクだって寝たい時がある
– 「XX分後に起こしてー」
– 「XXがあったら起こしてー」
2016/04/08 荒川 祐真 121
タスクのスリープについて
●
タスクだって寝たい時がある
– 「XX分後に起こしてー」
– 「XXがあったら起こしてー」
OS5では、タスクについて、以下を登録できる
・ウェイクアップタイマー
・ウェイクアップイベント
2016/04/08 荒川 祐真 122
タスクのスリープについて
●
ウェイクアップタイマー(目覚し時計)
– 関数: wakeup_after_msec(unsigned int msec)
– 「XXms後に起こしてー」
●
ウェイクアップイベント(目覚ましイベント)
– 関数: wakeup_after_event(unsigned char event_type)
– 「XXが起きたら起こしてー」
– 今、対応しているイベントは「キーボード入力」のみ
2016/04/08 荒川 祐真 123
タスクのスリープについて
どのように実現しているのか?
2016/04/08 荒川 祐真 124
タスクのスリープについて
どのように実現しているのか?
ランキューから抜いたり追加したりする
2016/04/08 荒川 祐真 125
タスクのスリープについて
どのように実現しているのか?
ランキュー
shell
uptime
2016/04/08 荒川 祐真 126
タスクのスリープについて
どのように実現しているのか?
ランキュー
shell
uptime
33ms後に
起こしてー
※ タイマー割り込みの粒度が10msなので、
  実際は40ms後に起こされる
2016/04/08 荒川 祐真 127
タスクのスリープについて
どのように実現しているのか?
ランキュー
shell
uptime
ウェイクアップキュー
2016/04/08 荒川 祐真 128
タスクのスリープについて
どのように実現しているのか?
ランキュー
shell
uptime
ウェイクアップキュー
以降、shellのみ実行
2016/04/08 荒川 祐真 129
タスクのスリープについて
どのように実現しているのか?
ランキュー
shell
uptime
ウェイクアップキュー
タイマー割り込み発生
33ms以上経過
2016/04/08 荒川 祐真 130
タスクのスリープについて
どのように実現しているのか?
ランキュー
shell
uptime
ウェイクアップキュー
ランキューに戻す
2016/04/08 荒川 祐真 131
タスクの構造
タスクを管理する構造体: struct task
ウェイクアップキュー
への追加時の
ウェイクアップ要因
管理用
unsigned int
wakeup_after_msec;
unsigned char
wakeup_after_event;
2016/04/08 荒川 祐真 132
スリープでのコンテキストスイッチ
による問題
時間
10ms 10ms 10ms
タイマー割り込み
によるコンテキストスイッチ
2016/04/08 荒川 祐真 133
時間
10ms 10ms 10ms
shell
キー入力待ち
スリープでのコンテキストスイッチ
による問題
2016/04/08 荒川 祐真 134
時間
10ms 10ms 10ms
shell uptime
ちょっとしか
実行できない・・・
スリープでのコンテキストスイッチ
による問題
2016/04/08 荒川 祐真 135
●
自らスリープした時は、
「タイムスライスの残りを他タスクにプレゼント」と判断
時間
10ms 10ms 10ms
shell uptime uptime
スリープでのコンテキストスイッチ
による問題
2016/04/08 荒川 祐真 136
タスクの構造
タスクを管理する構造体: struct task
コンテキストスイッチ時、
タイムスライスを
使い切ったか否かの
判別用
char
task_switched_in_time_slice;
2016/04/08 荒川 祐真 137
OS5の機能構成(ソースコード構成)
2015/04/05
2015/08/24
2015/10/31
2015/11/30
2016/02/08
日付(ブログ記事投稿)
総
コード
行数
【主な追加機能】
●
タスク管理
(スケジューラによる
タスクスリープ/ウェイクアップ)
●
省電力機能
●
特権管理
●
システムコール
2016/04/08 荒川 祐真 138
カーネル
時間
管理
デバイスドライバ
アプリ shell uptime
コンソール
CPU メモリ KBC CRTCPIT
:機能の呼び出し関係
タスク管理
スケジューラ
メモリ管理
ページング
ソ
フ
ト
ハ
ー
ド
OS5カーネルのアーキテクチャ
2016/04/08 荒川 祐真 139
カーネルタスク
●
省電力機能
ランキューに何も無いときには、カーネルタスクを実行
ランキュー
空
カーネル
タスク
2016/04/08 荒川 祐真 140
カーネルタスク
●
省電力機能
ランキューに何も無いときには、カーネルタスクを実行
ランキュー
空
カーネル
タスク
hlt命令を実行
割り込みがあるまで
CPUを休ませる
2016/04/08 荒川 祐真 141
関連するソースコード
●
カーネルタスク
– os5/kernel/kern_task_init.c
– os5/kernel/include/kern_task.h
●
カーネル初期化
– os5/kernel/init.c
2016/04/08 荒川 祐真 142
関連するソースコード
●
カーネルタスク
– os5/kernel/kern_task_init.c
– os5/kernel/include/kern_task.h
●
カーネル初期化
– os5/kernel/init.c
2016/04/08 荒川 祐真 143
関連するソースコード
●
カーネルタスク
– os5/kernel/kern_task_init.c
– os5/kernel/include/kern_task.h
●
カーネル初期化
– os5/kernel/init.c
カーネル初期化関数(kern_init)が
カーネルの初期化後、
カーネルタスクとして振る舞う
kern_init関数の末尾
2016/04/08 荒川 祐真 144
コード行数の推移
2015/04/05
2015/08/24
2015/10/31
2015/11/30
2016/02/08
日付(ブログ記事投稿)
総
コード
行数
【主な追加機能】
●
タスク管理
(スケジューラによる
タスクスリープ/ウェイクアップ)
●
省電力機能
●
特権管理
●
システムコール
2016/04/08 荒川 祐真 145
カーネル
時間
管理
デバイスドライバ
アプリ shell uptime
コンソール
CPU メモリ KBC CRTCPIT
:機能の呼び出し関係
タスク管理
スケジューラ
メモリ管理
ページング
ソ
フ
ト
ハ
ー
ド
OS5カーネルのアーキテクチャ
2016/04/08 荒川 祐真 146
x86 CPUの特権レベル
●
x86 CPUには0〜3の4つの特権レベルがある
– 番号が大きくなると、特権が低くなる
●
OS5カーネルでは0と3の特権レベルを使用
– カーネル: 特権レベル0
– タスク : 特権レベル3
●
特権レベルは、
TSSを定義するセグメントディスクリプタに設定
2016/04/08 荒川 祐真 147
x86 CPUの特権レベル
●
x86 CPUには0〜3の4つの特権レベルがある
– 番号が大きくなると、特権が低くなる
●
OS5カーネルでは0と3の特権レベルを使用
– カーネル: 特権レベル0
– タスク : 特権レベル3
●
特権レベルは、
TSSを定義するセグメントディスクリプタに設定
2016/04/08 荒川 祐真 148
そもそも、「セグメント」とは
【セグメンテーション】
●
アドレス空間を「ベースアドレス」と「リミット」で分割し、
管理する方式
●
分割した領域を「セグメント」と呼ぶ
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
セグメント
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
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
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
ベースアドレスとリミットは、
セグメントディスクリプタに含まれている
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
特権レベルはここに設定する
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
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
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
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
2016/04/08 荒川 祐真 158
コード行数の推移
2015/04/05
2015/08/24
2015/10/31
2015/11/30
2016/02/08
日付(ブログ記事投稿)
総
コード
行数
【主な追加機能】
●
タスク管理
(スケジューラによる
タスクスリープ/ウェイクアップ)
●
省電力機能
●
特権管理
●
システムコール
2016/04/08 荒川 祐真 159
カーネル
時間
管理
システムコール
デバイスドライバ
アプリ shell uptime
コンソール
CPU メモリ KBC CRTCPIT
:機能の呼び出し関係
タスク管理
スケジューラ
メモリ管理
ページング
ソ
フ
ト
ハ
ー
ド
OS5カーネルのアーキテクチャ
2016/04/08 荒川 祐真 160
システムコールとは
●
OS5において、
アプリケーションがカーネルとやり取りする
ための唯一のインタフェース
2016/04/08 荒川 祐真 161
実装
●
アプリケーションは
ユーザーの特権レベルで動作
●
カーネル空間の関数を呼ぶことはできない
●
カーネル空間の機能を呼び出すために、
「ソフトウェア割り込み」を使用
2016/04/08 荒川 祐真 162
動作例
shell kernel
3
現在の特権レベル EAX
EBX
ECX
EDX
汎用レジスタ
2016/04/08 荒川 祐真 163
動作例
shell kernel
3
現在の特権レベル EAX
EBX
ECX
EDX
汎用レジスタ
shell動作中
2016/04/08 荒川 祐真 164
動作例
shell kernel
3
現在の特権レベル EAX
EBX
ECX
EDX
汎用レジスタ
“Hello”と
画面に表示したい
2016/04/08 荒川 祐真 165
動作例
shell kernel
3
現在の特権レベル EAX
EBX
ECX
EDX
汎用レジスタ
CON_PUT_STR
システムコール
(文字列をコンソール上に
出力するシステムコール)
を実行したい
2016/04/08 荒川 祐真 166
動作例
shell kernel
3
現在の特権レベル EAX
EBX
ECX
EDX
汎用レジスタ
【前提条件】
アプリケーションとカーネルの間で、
以下の合意が取れている
●
システムコールに使用する割り込み番号
●
汎用レジスタを使用した値受け渡し方法
2016/04/08 荒川 祐真 167
動作例
shell kernel
3
現在の特権レベル CON_PUT_STR(定数)EAX
“Hello”の先頭アドレスEBX
ECX
EDX
汎用レジスタ
EAXにシステムコールIDを、
EBX〜EDXに第1〜第3引数を設定
2016/04/08 荒川 祐真 168
動作例
shell kernel
3
現在の特権レベル CON_PUT_STR(定数)EAX
“Hello”の先頭アドレスEBX
ECX
EDX
汎用レジスタ
int $0x80
ソフトウェア割り込み実行
※ OS5カーネルでは、0x80番のソフトウェア割り込みを
 システムコールとして使用する
2016/04/08 荒川 祐真 169
動作例
shell kernel
0
現在の特権レベル CON_PUT_STR(定数)EAX
“Hello”の先頭アドレスEBX
ECX
EDX
汎用レジスタ
特権レベル昇格
0x80番の割り込みハンドラ
が呼び出される
2016/04/08 荒川 祐真 170
動作例
shell kernel
0
現在の特権レベル CON_PUT_STR(定数)EAX
“Hello”の先頭アドレスEBX
ECX
EDX
汎用レジスタ
割り込みハンドラ内で
以下を実行
1. EAXで対象の
 システムコールを確認
2. システムコールに対応
 するカーネル内の関数
 を実行
3. 戻り値をEAXに設定
4. 割り込みからリターン
2016/04/08 荒川 祐真 171
動作例
shell kernel
3
現在の特権レベル CON_PUT_STR(定数)EAX
“Hello”の先頭アドレスEBX
ECX
EDX
汎用レジスタ
元の特権レベルに戻る
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 ファイルシステム: ファイルを実行する
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 ファイルシステム: ファイルを実行する
システムコール部分の完成度としては、
まだ「システムコールの枠組みができあがった」くらい
「カーネルとしてどのようなシステムコールを用意するか」
という観点で、
システムコールのラインナップ自体は今後変更していく予定
2016/04/08 荒川 祐真 174
関連するソースコード
● os5/kernel/sys.S
● os5/kernel/syscall.c
● os5/kernel/include/syscall.h
2016/04/08 荒川 祐真 175
コード行数の推移
2015/04/05
2015/08/24
2015/10/31
2015/11/30
2016/02/08
日付(ブログ記事投稿)
総
コード
行数
【主な追加機能】
●
ファイルシステム
●
メモリ管理
(メモリアロケータ)
●
タスク管理
(タスクローダ)
2016/04/08 荒川 祐真 176
コード行数の推移
2015/04/05
2015/08/24
2015/10/31
2015/11/30
2016/02/08
日付(ブログ記事投稿)
総
コード
行数
【主な追加機能】
●
ファイルシステム
●
メモリ管理
(メモリアロケータ)
●
タスク管理
(タスクローダ)
2016/04/08 荒川 祐真 177
カーネル
時間
管理
ファイルシステム
システムコール
デバイスドライバ
アプリ shell uptime
コンソール
CPU メモリ KBC CRTCPIT
:機能の呼び出し関係
タスク管理
スケジューラ
メモリ管理
ページング
ソ
フ
ト
ハ
ー
ド
OS5カーネルのアーキテクチャ
2016/04/08 荒川 祐真 178
なんのためのもの?
●
単なるバイナリ列を、
「ファイル」として扱うためのルール決め
●
OS5の場合、全てのデータは、
ブートローダーがRAMにロードする
●
RAM上の「ユーザーランド領域」の
バイナリ列のルールを決めている
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
2016/04/08 荒川 祐真 180
OS5の現在のファイルシステム
ユーザーランド領域 0x0001 1000
0x0001 3FFF
0x0001 2000
0x0001 3000
【ルール1】
先頭4KBにコントロールブロックを
配置
2016/04/08 荒川 祐真 181
OS5の現在のファイルシステム
ユーザーランド領域 0x0001 1000
0x0001 3FFF
2
0x0001 2000
0x0001 3000
【ルール2】
コントロールブロックには
存在するファイル数を格納
2016/04/08 荒川 祐真 182
OS5の現在のファイルシステム
ユーザーランド領域 0x0001 1000
0x0001 3FFF
0x0001 2000
0x0001 3000
【ルール3】
ファイルは4KB以内
4KB
4KB
2016/04/08 荒川 祐真 183
OS5の現在のファイルシステム
ユーザーランド領域 0x0001 1000
0x0001 3FFF
0x0001 2000
0x0001 3000
【ルール4】
ファイルの先頭32バイトに
ファイル名を格納
shell
uptime
2016/04/08 荒川 祐真 184
OS5の現在のファイルシステム
ユーザーランド領域 0x0001 1000
0x0001 3FFF
0x0001 2000
0x0001 3000
【ルール5】
ファイルの先頭33バイト以降に
ファイル本体を格納
ファイル本体を
配置
2016/04/08 荒川 祐真 185
OS5の現在のファイルシステム
ユーザーランド領域 0x0001 1000
0x0001 3FFF
0x0001 2000
0x0001 3000
【ルール6】
ファイルを実行する際は、
先頭33バイト目にジャンプする
2016/04/08 荒川 祐真 186
OS5の現在のファイルシステム
ユーザーランド領域 0x0001 1000
0x0001 3FFF
0x0001 2000
0x0001 3000
【ルール6】
ファイルを実行する際は、
先頭33バイト目にジャンプする
os5/apps/app.lc
2016/04/08 荒川 祐真 187
OS5の現在のファイルシステム
ユーザーランド領域 0x0001 1000
0x0001 3FFF
0x0001 2000
0x0001 3000
【ルール6】
ファイルを実行する際は、
先頭33バイト目にジャンプする
os5/apps/app.lc
0x2000 0000
(アプリバイナリを
配置する先頭のVA)
+
0x20
(32バイト分飛ばした先)
2016/04/08 荒川 祐真 188
OS5の現在のファイルシステム
ユーザーランド領域 0x0001 1000
0x0001 3FFF
0x0001 2000
0x0001 3000
【ルール6】
ファイルを実行する際は、
先頭33バイト目にジャンプする
os5/apps/app.lc
textセクション
(コンパイル結果の機械語を
配置するセクション)を
先頭に配置
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)の
一番先頭で定義
2016/04/08 荒川 祐真 190
OS5の現在のファイルシステム
ユーザーランド領域 0x0001 1000
0x0001 3FFF
0x0001 2000
0x0001 3000
【ルール6】
ファイルを実行する際は、
先頭33バイト目にジャンプする
TSSの一部
EIP
2016/04/08 荒川 祐真 191
OS5の現在のファイルシステム
ユーザーランド領域 0x0001 1000
0x0001 3FFF
0x0001 2000
0x0001 3000
【ルール6】
ファイルを実行する際は、
先頭33バイト目にジャンプする
TSSの一部
EIP
タスク初期化時、
EIPに 0x2000 0020 を設定
2016/04/08 荒川 祐真 192
ファイルの構造
ファイルを管理する構造体: struct file
2016/04/08 荒川 祐真 193
ファイルの構造
ファイルを管理する構造体: struct file
2016/04/08 荒川 祐真 194
ファイルシステムの初期化
ファイルシステム内を検索し、
struct fileのリンクリストを作成
0x0001 1000
0x0001 3FFF
0x0001 2000
0x0001 3000
shell
uptime
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
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
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
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
2016/04/08 荒川 祐真 199
関連するソースコード
● os5/kernel/fs.c
● os5/kernel/include/fs.h
● os5/tools/make_os5_fs.sh
– アプリケーションバイナリから
ファイルシステムを生成する
シェルスクリプト
2016/04/08 荒川 祐真 200
コード行数の推移
2015/04/05
2015/08/24
2015/10/31
2015/11/30
2016/02/08
日付(ブログ記事投稿)
総
コード
行数
【主な追加機能】
●
ファイルシステム
●
メモリ管理
(メモリアロケータ)
●
タスク管理
(タスクローダ)
2016/04/08 荒川 祐真 201
カーネル
時間
管理
ファイルシステム
システムコール
デバイスドライバ
アプリ shell uptime
コンソール
CPU メモリ KBC CRTCPIT
:機能の呼び出し関係
タスク管理
スケジューラ
メモリ管理
ページング
メモリアロケータ
ソ
フ
ト
ハ
ー
ド
OS5カーネルのアーキテクチャ
2016/04/08 荒川 祐真 202
メモリアロケータ
●
どのようなものか?
– メモリ上にヒープ領域を設定
– メモリの動的確保を要求された時、
ヒープ領域からメモリを確保し、要求者へ与える
●
OS5の場合、固定長(4KB)
– ヒープ領域内の使用状況の管理も行う
2016/04/08 荒川 祐真 203
メモリアロケータ
コンベンショナルメモリ 0x0000 0500
0x0009 FFFF
ヒープ領域
(44.0KB)
0x0009 5000 〜 0x0009 FFFF
0x0008 0000
2016/04/08 荒川 祐真 204
メモリアロケータ
ヒープ領域 0x0009 5000
0x0009 FFFF
2016/04/08 荒川 祐真 205
メモリアロケータ
ヒープ領域 0x0009 5000
0x0009 FFFF
固定長(4KB)で分割
2016/04/08 荒川 祐真 206
メモリアロケータ
ヒープ領域 0x0009 5000
0x0009 FFFF
メモリ動的確保の要求があれば、
4KBずつ与える
タスク管理
uptimeタスク用に
スタック領域を
確保したい
2016/04/08 荒川 祐真 207
メモリアロケータ
ヒープ領域 0x0009 5000
0x0009 FFFF
メモリ動的確保の要求があれば、
4KBずつ与える
タスク管理
メモリちょうだい
mem_alloc()
メモリ
アロケータ
2016/04/08 荒川 祐真 208
メモリアロケータ
ヒープ領域 0x0009 5000
0x0009 FFFF
メモリ動的確保の要求があれば、
4KBずつ与える
タスク管理 メモリ
アロケータ
使ってないヤツ
見つけた!
2016/04/08 荒川 祐真 209
メモリアロケータ
ヒープ領域 0x0009 5000
0x0009 FFFF
メモリ動的確保の要求があれば、
4KBずつ与える
タスク管理 メモリ
アロケータ
使用中の目印を
付けておこう
2016/04/08 荒川 祐真 210
メモリアロケータ
ヒープ領域 0x0009 5000
0x0009 FFFF
メモリ動的確保の要求があれば、
4KBずつ与える
タスク管理 メモリ
アロケータ
使用中の目印を
付けておこう heap_alloc_table
という配列で管理
2016/04/08 荒川 祐真 211
メモリアロケータ
ヒープ領域 0x0009 5000
0x0009 FFFF
メモリ動的確保の要求があれば、
4KBずつ与える
タスク管理 メモリ
アロケータ
確保できたよ
0x0009 5000
2016/04/08 荒川 祐真 212
メモリアロケータ
ヒープ領域 0x0009 5000
0x0009 FFFF
メモリ動的確保の要求があれば、
4KBずつ与える
タスク管理 メモリ
アロケータ
0x0009 5000から
4KBの領域を
uptimeのスタックに使おう
2016/04/08 荒川 祐真 213
コード行数の推移
2015/04/05
2015/08/24
2015/10/31
2015/11/30
2016/02/08
日付(ブログ記事投稿)
総
コード
行数
【主な追加機能】
●
ファイルシステム
●
メモリ管理
(メモリアロケータ)
●
タスク管理
(タスクローダ)
2016/04/08 荒川 祐真 214
カーネル
時間
管理
ファイルシステム
システムコール
デバイスドライバ
アプリ shell uptime
コンソール
CPU メモリ KBC CRTCPIT
:機能の呼び出し関係
タスク管理
スケジューラ
タスクローダ
メモリ管理
ページング
メモリアロケータ
ソ
フ
ト
ハ
ー
ド
OS5カーネルのアーキテクチャ
2016/04/08 荒川 祐真 215
タスクローダとは
●
役割
1.ファイルシステム上からファイルを見つける
2.新たなタスクのためのメモリを確保
3.タスクの構造を用意し、初期化
2016/04/08 荒川 祐真 216
タスクローダとは
●
役割
1.ファイルシステム上からファイルを見つける
2.新たなタスクのためのメモリを確保
3.タスクの構造を用意し、初期化
ファイルシステム
2016/04/08 荒川 祐真 217
タスクローダとは
●
役割
1.ファイルシステム上からファイルを見つける
2.新たなタスクのためのメモリを確保
3.タスクの構造を用意し、初期化
ファイルシステム
メモリ管理
2016/04/08 荒川 祐真 218
タスクローダとは
●
役割
1.ファイルシステム上からファイルを見つける
2.新たなタスクのためのメモリを確保
3.タスクの構造を用意し、初期化
ファイルシステム
メモリ管理
タスク管理
2016/04/08 荒川 祐真 219
タスクローダとは
●
役割
1.ファイルシステム上からファイルを見つける
2.新たなタスクのためのメモリを確保
3.タスクの構造を用意し、初期化
ファイルシステム
メモリ管理
タスク管理
カーネルの複数の機能の集大成
2016/04/08 荒川 祐真 220
タスクの生成
●
タスクを生成する際は、
以下の領域のためのメモリを動的に確保し、
それぞれ初期化する
– TSS
– スタック領域
– ページディレクトリ・ページテーブル
2016/04/08 荒川 祐真 221
タスクの初期化
os5/kernel/task.c の task_init 関数の動作を見てみる
2016/04/08 荒川 祐真 222
タスクの初期化
① 引数でstruct fileのポインタを受け取る
struct listuptimeの
struct file next
prev
char *name
void
*data_base_addr
2016/04/08 荒川 祐真 223
タスクの初期化
② タスク作成に必要なメモリを動的確保
struct listuptimeの
struct file next
prev
char *name
void
*data_base_addr
PD用
PT用
struct task用
スタック用
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
2016/04/08 荒川 祐真 225
タスクの初期化
④ タスクIDを作成・設定
struct listuptimeの
struct file next
prev
char *name
void
*data_base_addr
struct task用
スタック用
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
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
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
2016/04/08 荒川 祐真 229
タスクの構造
タスクを管理する構造体: struct task
2016/04/08 荒川 祐真 230
タスクの構造
タスクを管理する構造体: struct task
void (*context_switch)(void);
unsigned char
context_switch_func[CONTEXT_SWITCH_FN_SIZE]
2016/04/08 荒川 祐真 231
タスクの構造
タスクを管理する構造体: struct task
void (*context_switch)(void);
unsigned char
context_switch_func[CONTEXT_SWITCH_FN_SIZE]
●
本来必要ないメンバ
● jmp命令でのコンテキストスイッチが
オペランド即値指定でしか動作確認できていない
● 仕方なく、jmp命令の機械語をcharの配列に格納し、
タスク生成時、「生成したタスクへコンテキストスイッチする命令」へ
機械語を直接書き換えている
jmp TSSのアドレス
ここが即値指定の場合しか、
正常動作を確認できていない
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
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
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)
タスク用スタック
カーネル用スタック
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)
タスク用スタック
カーネル用スタック
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)
タスク用スタック
カーネル用スタック
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)
タスク用スタック
カーネル用スタック
スタック用
2016/04/08 荒川 祐真 238
【再掲】OS5の現在のメモリマップ
コンベンショナルメモリ 0x0000 0500
0x0009 FFFF
カーネルスタック領域
(436.0KB)
0x0001 3000 〜 0x0007 FFFF
0x0008 0000カーネルスタックの
ベースアドレス
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
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
2016/04/08 荒川 祐真 241
今日お話する内容
1.はじめに
2.OS5の概観
3.カーネル
4.おわりに
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 ファイルシステム: ファイルを実行する
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のシステムコールは粒度がまちまち
<<現在のシステムコールの問題点>>
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のシステムコールは粒度がまちまち
●
制御するデバイスの数だけシステムコールが必要になる
<<現在のシステムコールの問題点>>
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
という共通のシステムコールで制御できるようにしている
<<現在のシステムコールの問題点>>
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
という共通のシステムコールで制御できるようにしている
→ 「既存のものにただ合わせる」ということはしたく無く、
  「ファイル」という概念すら新しい物に置き換えてみたかったが、
  それ以上にシンプルにできるものが思いつかない・・・
<<現在のシステムコールの問題点>>
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を作った人は本当に頭が良いと思います。。
<<現在のシステムコールの問題点>>
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を作った人は本当に頭が良いと思います。。
<<現在のシステムコールの問題点>>
古きをたずねて、
先人の偉大さを知りました
2016/04/08 荒川 祐真 249
ご清聴ありがとうございました
2016/04/08 荒川 祐真 250
以降、付録です
時間の関係で割愛した説明や、
別の言い方での説明など
参考までに残しておきます
2016/04/08 荒川 祐真 251
現状のブートローダーについて
●
ハードウェアをセットアップし、
カーネルの先頭アドレスへジャンプする
●
MBRの512バイトそのもの
– 0x0000 7c00 〜 0x0000 7dff
●
現状は、全てアセンブラで記述
2016/04/08 荒川 祐真 252
現状のブートローダーについて
●
ハードウェアをセットアップし、
カーネルの先頭アドレスへジャンプする
少しブレークダウン
1. BIOS割り込みルーチンで
ハードウェア初期化とRAMへのロード
2. CPUのモード変更
3. カーネルの先頭アドレスへジャンプ
2016/04/08 荒川 祐真 253
現状のブートローダーについて
●
ハードウェアをセットアップし、
カーネルの先頭アドレスへジャンプする
少しブレークダウン
1. BIOS割り込みルーチンで
ハードウェア初期化とRAMへのロード
2. CPUのモード変更
3. カーネルの先頭アドレスへジャンプ
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ビットモード(リアルモード)の
み
2016/04/08 荒川 祐真 255
現状のブートローダーについて
●
ハードウェアをセットアップし、
カーネルの先頭アドレスへジャンプする
少しブレークダウン
1. BIOS割り込みルーチンで
ハードウェア初期化とRAMへのロード
2. CPUのモード変更
3. カーネルの先頭アドレスへジャンプ
2016/04/08 荒川 祐真 256
現状のブートローダーについて
●
ハードウェアをセットアップし、
カーネルの先頭アドレスへジャンプする
少しブレークダウン
1. BIOS割り込みルーチンで
ハードウェア初期化とRAMへのロード
2. CPUのモード変更
3. カーネルの先頭アドレスへジャンプ
16ビット → 32ビット
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>
開いたファイルを
実行
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後に設定し、
スリープ
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つ使われている
– マスターとスレーブ
– スレーブの割り込み出力がマスターの割り込み入力に
接続されている
2016/04/08 荒川 祐真 260
ページングとは?
●
仮想記憶(仮想メモリ)を実現する方式
●
メモリを「ページ」という単位で分割して管理する
RAM
アーキテクチャにもよるが、
OS5やLinux(x86)では4KB
ページ
2016/04/08 荒川 祐真 261
ページングとは?
●
複数のタスクを同時に実行する際、実行時に必要なページ
のみロード
RAM
TaskA TaskB
ページイン
HDDなどの補助記憶
ページアウト
2016/04/08 荒川 祐真 262
OS5でのページング
●
とはいえ、OS5においてはカーネル・アプリ全
てメモリに乗るサイズ
– ページイン・ページアウトも発生せず、実装もして
いない
●
ページングについては「仮想メモリ」の観点で
使用している
2016/04/08 荒川 祐真 263
「変換表」について
●
実際には「ページディレクトリ(PD)」と
「ページテーブル(PT)」の2種類
ページテーブルページディレクトリ
表の各行は
「エントリ」
と呼ばれる
ページディレクトリエントリ
(PDE)
ページテーブルエントリ
(PTE)
2016/04/08 荒川 祐真 264
「変換表」について
●
実際には「ページディレクトリ(PD)」と
「ページテーブル(PT)」の2種類
ページテーブルページディレクトリ
ページディレクトリエントリは、
ページテーブルの先頭アドレスを指す
2016/04/08 荒川 祐真 265
「変換表」について
ページテーブルページディレクトリ ページ
4KB
4KB
4KB
4KB
PTEが
ページの先頭アドレスを指す
2016/04/08 荒川 祐真 266
「変換表」について
ページテーブルページディレクトリ ページ
4KB
4KB
4KB
4KB
CR3 CPUのCR3というレジスタに
PDの先頭アドレスが格納されている
※ 別名:PDBR(Page Directory Base Register)
2016/04/08 荒川 祐真 267
「変換表」について
ページテーブルページディレクトリ ページ
4KB
4KB
4KB
4KB
CR3
VA→PAのアドレス変換は
階層構造
2016/04/08 荒川 祐真 268
VAはオフセットの塊
●
PD・PT・ページ内のオフセットは
どこで指定するのか?
2016/04/08 荒川 祐真 269
VAはオフセットの塊
●
PD・PT・ページ内のオフセットは
どこで指定するのか?
全てVAに含まれている
2016/04/08 荒川 祐真 270
【補足】TLB
●
PD・PTはメモリ上にあるため、
1度のメモリアクセスにつき、
PD・PTへのアクセスのために余分にメモリへ
アクセスしなければならない
●
アドレス変換高速化のため、
PDEとPTEをキャッシュするものとして
TLB(トランスレーションルックアサイドバッファ)が
存在する
ページングでは、アドレス変換にかかる時間がボトルネック
2016/04/08 荒川 祐真 271
コード行数の推移
OS5の各機能は、以下のように実装されてきた
2015/04/05
2015/08/24
2015/10/31
2015/11/30
2016/02/08システムコールの他、
特権管理、省電力機能、
ロック機能
追加
日付(ブログ記事投稿)
総
コード
行数
2016/04/08 荒川 祐真 272
OS5カーネルのアーキテクチャ
カーネル
時間
管理
ファイルシステム
システムコール
デバイスドライバ
アプリ shell uptime
コンソール
CPU メモリ KBC CRTCPIT
:機能の呼び出し関係
タスク管理
スケジューラ
タスクローダ
メモリ管理
ページング
メモリアロケータ
ソ
フ
ト
ハ
ー
ド
【ロック機能】
アプリケーションから
呼び出されるものではないが、
カーネルの基本機能の一つ
2016/04/08 荒川 祐真 273
ロック機能
●
役割
– 「ここだけは割り込んで欲しくない」・「他のタス
クへ遷移して欲しくない」という区間でロックする
●
やっていること
– CPUのEFLAGSレジスタのIF(割り込みイネーブル
フラグ)
2016/04/08 荒川 祐真 274
ロック機能: 入れ子の場合の問題点
●
入れ子にするとロックしたい区間にも関わら
ず、ロックが解除されてしまう
2016/04/08 荒川 祐真 275
ロック機能: 入れ子問題の対処
●
実際には「単にレジスタの制御をするだけ」で
はなく、ロック状態の退避・復帰を行っている
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”を受け取った
とする
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を持つものを探す
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
②見つけた
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の
先頭アドレスを返す
2016/04/08 荒川 祐真 280
システムコール: exec
●
システムコールexecはタスク管理の機能
●
引数でstruct fileのポインタを受け取る
●
内部的には単にタスク管理のtask_init関数を呼
び出すだけ
– task_init関数はstruct fileのポインタを引数とする
2016/04/08 荒川 祐真 281
失敗談: ltr命令でリブート
●
現象
– ltr命令によりタスクレジスタへロードさせる
と、QEMU上でリブートしてしまう
●
原因/解決方法
– GDTの4つ目にTSSのディスクリプタを配置してい
たが、lgdtでGDTの範囲がディスクリプタ3つ分の
ままだった
2016/04/08 荒川 祐真 282
失敗談: コンテキストスイッチの
ljmp実行でリブートを繰り返す
●
現象
– コンテキストスイッチのljmp実行でリブートを繰り
返す
●
原因/解決方法
– shellのTSSのCR3が初期化されていなかったことが
問題であった
2016/04/08 荒川 祐真 283
失敗談: キー入力時、ゴミが入る
●
現象
– キー入力時、ゴミが入る
●
原因/解決方法
– デキューとエラーステータス確認の間に、キーボー
ド割り込みからのエンキューが入り、エラーステー
タスが上書きされてしまっていたことが原因であっ
た
2016/04/08 荒川 祐真 284
失敗談: 作成したPTEを使用すると
ブート・リブートを繰り返す
●
現象
– 作成したPTEを使用するとブート・リブートを繰り
返す
– uptimeを無効化(タイマ割り込み無効化)で発生しな
くなる
●
原因/解決方法
– PD初期化を間違っていた
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
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の領
域を壊した時リブート

More Related Content

PPTX
CyberChefの使い方(HamaCTF2019 WriteUp編)
PDF
UEFIベアメタルプログラミング
PDF
今日から使おうSmalltalk
PDF
できる!並列・並行プログラミング
PPTX
Docker超入門
PPTX
Linuxのsemaphoreとmutexを見る 
PDF
PacemakerのMaster/Slave構成の基本と事例紹介(DRBD、PostgreSQLレプリケーション) @Open Source Confer...
PDF
目grep入門 +解説
CyberChefの使い方(HamaCTF2019 WriteUp編)
UEFIベアメタルプログラミング
今日から使おうSmalltalk
できる!並列・並行プログラミング
Docker超入門
Linuxのsemaphoreとmutexを見る 
PacemakerのMaster/Slave構成の基本と事例紹介(DRBD、PostgreSQLレプリケーション) @Open Source Confer...
目grep入門 +解説

What's hot (20)

PPTX
Verilator勉強会 2021/05/29
PDF
Linux-HA Japanプロジェクトのこれまでとこれから
PDF
C++ マルチスレッド 入門
PDF
DSIRNLP #3 LZ4 の速さの秘密に迫ってみる
PDF
ARM CPUにおけるSIMDを用いた高速計算入門
PDF
UE4プログラマー勉強会 in 大阪 -エンジンの内部挙動について
PPTX
OSを手作りするという趣味と仕事
PPTX
30分で分かる!OSの作り方
PPTX
冬のLock free祭り safe
PPTX
実践的Reaper勉強会
PDF
Apache Airflow入門 (マーケティングデータ分析基盤技術勉強会)
PDF
Rancher/Kubernetes入門ハンズオン資料~第2回さくらとコンテナの夕べ #さくらの夕べ 番外編
PDF
ラズパイでデバイスドライバを作ってみた。
PPTX
UEFIによるELFバイナリの起動
PPTX
イベント駆動プログラミングとI/O多重化
PDF
【Unity道場 2月】シェーダを書けるプログラマになろう
PDF
VirtualBox と Rocky Linux 8 で始める Pacemaker ~ VirtualBox でも STONITH 機能が試せる! Vi...
PDF
UE4のシーケンサーをもっともっと使いこなそう!最新情報・Tipsをご紹介!
PDF
Rust で RTOS を考える
PDF
Oss貢献超入門
Verilator勉強会 2021/05/29
Linux-HA Japanプロジェクトのこれまでとこれから
C++ マルチスレッド 入門
DSIRNLP #3 LZ4 の速さの秘密に迫ってみる
ARM CPUにおけるSIMDを用いた高速計算入門
UE4プログラマー勉強会 in 大阪 -エンジンの内部挙動について
OSを手作りするという趣味と仕事
30分で分かる!OSの作り方
冬のLock free祭り safe
実践的Reaper勉強会
Apache Airflow入門 (マーケティングデータ分析基盤技術勉強会)
Rancher/Kubernetes入門ハンズオン資料~第2回さくらとコンテナの夕べ #さくらの夕べ 番外編
ラズパイでデバイスドライバを作ってみた。
UEFIによるELFバイナリの起動
イベント駆動プログラミングとI/O多重化
【Unity道場 2月】シェーダを書けるプログラマになろう
VirtualBox と Rocky Linux 8 で始める Pacemaker ~ VirtualBox でも STONITH 機能が試せる! Vi...
UE4のシーケンサーをもっともっと使いこなそう!最新情報・Tipsをご紹介!
Rust で RTOS を考える
Oss貢献超入門
Ad

Viewers also liked (20)

PDF
QEMUでARM64bitベアメタルプログラミング
PDF
C++でできる!OS自作入門
PDF
「アイロンビーズプロッター作ろうとしてみた with プロ生ちゃん」 プロ生勉強会 第44回@熊本
PDF
「明日からできる!面白ガジェットの作り方」 プロ生勉強会 第35回@DMM.comラボ
PDF
30日でできない!コンピューター自作入門 - カーネル/VM探検隊@つくば
PDF
やってよかったOS作り
PPTX
ゼロから始める自作 CPU 入門
PDF
ハッキング実演
PDF
低レイヤー入門
PDF
組込みOSを作ってみよう!(オープンソースカンファレンス内セミナー資料)
PDF
【学習メモ#1st】12ステップで作る組込みOS自作入門
PDF
バイナリより低レイヤな話 (プロセッサの心を読み解く) - カーネル/VM探検隊@北陸1
PDF
今さら聞けない Linux コマンドラインツールテクニック その1 rev. 2
PDF
CTF超入門 (for 第12回セキュリティさくら)
PDF
Subscriber Identity Module
PDF
今さら聞けない! Linux コマンドラインツールテクニック その1 rev. 3
PDF
Anko Kivy
PDF
NTT Docomo Device Hackathon
PDF
ふぃぎゅ@ホーム 2
PDF
フルスクラッチ自作OS(OS5)の紹介
QEMUでARM64bitベアメタルプログラミング
C++でできる!OS自作入門
「アイロンビーズプロッター作ろうとしてみた with プロ生ちゃん」 プロ生勉強会 第44回@熊本
「明日からできる!面白ガジェットの作り方」 プロ生勉強会 第35回@DMM.comラボ
30日でできない!コンピューター自作入門 - カーネル/VM探検隊@つくば
やってよかったOS作り
ゼロから始める自作 CPU 入門
ハッキング実演
低レイヤー入門
組込みOSを作ってみよう!(オープンソースカンファレンス内セミナー資料)
【学習メモ#1st】12ステップで作る組込みOS自作入門
バイナリより低レイヤな話 (プロセッサの心を読み解く) - カーネル/VM探検隊@北陸1
今さら聞けない Linux コマンドラインツールテクニック その1 rev. 2
CTF超入門 (for 第12回セキュリティさくら)
Subscriber Identity Module
今さら聞けない! Linux コマンドラインツールテクニック その1 rev. 3
Anko Kivy
NTT Docomo Device Hackathon
ふぃぎゅ@ホーム 2
フルスクラッチ自作OS(OS5)の紹介
Ad

Similar to 【2000行弱!】x86用自作カーネルの紹介 (20)

PDF
レガシーフリーOSに必要な要素技術 legacy free os
PDF
デバドラを書いてみよう!
PDF
[Basic 7] OS の基本 / 割り込み / システム コール / メモリ管理
PDF
【学習メモ#4th】12ステップで作る組込みOS自作入門
PPTX
あなたのAppleにもEFIモンスターはいませんか? by Pedro Vilaça - CODE BLUE 2015
PDF
retrobsd-2012-JUL-07 at JNUG BSD BoF
PDF
kagamicomput201705
PPT
d-kami x86-2
PDF
MeeGo Seminar Winter Porting 20101209
PDF
0章 Linuxカーネルを読む前に最低限知っておくべきこと
PDF
DOSBox for beginners はじめてのDOSBox
PDF
Sencha & Delphi Ready Studiy
PDF
最近遊んだLinuxボードたち
 
PPTX
ロボットシステム学2015年第5回
PDF
2011.06.11 v7から始めるunix まとめ
PDF
V6 unix vol.2 in okinawa
PPT
201104016 osc2011 kobe
PDF
NetBSD/evbarm on Raspberry Pi
PDF
x86_64向け自作OSの紹介
PPTX
組込みAndroid入門実習
レガシーフリーOSに必要な要素技術 legacy free os
デバドラを書いてみよう!
[Basic 7] OS の基本 / 割り込み / システム コール / メモリ管理
【学習メモ#4th】12ステップで作る組込みOS自作入門
あなたのAppleにもEFIモンスターはいませんか? by Pedro Vilaça - CODE BLUE 2015
retrobsd-2012-JUL-07 at JNUG BSD BoF
kagamicomput201705
d-kami x86-2
MeeGo Seminar Winter Porting 20101209
0章 Linuxカーネルを読む前に最低限知っておくべきこと
DOSBox for beginners はじめてのDOSBox
Sencha & Delphi Ready Studiy
最近遊んだLinuxボードたち
 
ロボットシステム学2015年第5回
2011.06.11 v7から始めるunix まとめ
V6 unix vol.2 in okinawa
201104016 osc2011 kobe
NetBSD/evbarm on Raspberry Pi
x86_64向け自作OSの紹介
組込みAndroid入門実習

More from Yuma Ohgami (20)

PDF
最近のGB向け独自OS活動について(「レトロゲーム勉強会#10」の発表スライド)
PDF
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
PDF
Daisy OSでデイジーワールド!
PDF
バイナリ生物学でデイジーワールド
PDF
OSC2023 Tokyo/Fall展示内容(予定)と技術書典15向け新刊(執筆中)のご紹介
PDF
去年「バイナリ生物学」で今年「PDP-7」だったのはなぜなのか?
PDF
60年代ゲームハードPDP-7のご紹介
PDF
来週の展示内容紹介
PDF
DaisyOS(仮)のご紹介
PDF
セキュリティ・ネクストキャンプ2022 オンライン [N9] バイナリ生物学入門
PDF
セキュリティ・ネクストキャンプ2022 オンライン [N5] バイナリ生物学入門
PDF
『へにゃぺんて』のこれまでを振り返るブログ記事の紹介
PDF
「へにゃぺんて」のこれまでを振り返るブログ記事の紹介
PDF
バイナリ生成環境『daisy-tools』のご紹介
PDF
セガサターンで動く自作シンセサイザーの紹介
PDF
セガサターンマシン語プログラミングの紹介
PDF
ハードの作りで振り返るセガサターン
PDF
エミュレータのコードを読んでわかるセガサターン
PDF
エミュレータのコードを読んでわかる「セガサターン」
PDF
シェルスクリプトでセガサターンマシン語ベアメタルプログラミング
最近のGB向け独自OS活動について(「レトロゲーム勉強会#10」の発表スライド)
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Daisy OSでデイジーワールド!
バイナリ生物学でデイジーワールド
OSC2023 Tokyo/Fall展示内容(予定)と技術書典15向け新刊(執筆中)のご紹介
去年「バイナリ生物学」で今年「PDP-7」だったのはなぜなのか?
60年代ゲームハードPDP-7のご紹介
来週の展示内容紹介
DaisyOS(仮)のご紹介
セキュリティ・ネクストキャンプ2022 オンライン [N9] バイナリ生物学入門
セキュリティ・ネクストキャンプ2022 オンライン [N5] バイナリ生物学入門
『へにゃぺんて』のこれまでを振り返るブログ記事の紹介
「へにゃぺんて」のこれまでを振り返るブログ記事の紹介
バイナリ生成環境『daisy-tools』のご紹介
セガサターンで動く自作シンセサイザーの紹介
セガサターンマシン語プログラミングの紹介
ハードの作りで振り返るセガサターン
エミュレータのコードを読んでわかるセガサターン
エミュレータのコードを読んでわかる「セガサターン」
シェルスクリプトでセガサターンマシン語ベアメタルプログラミング

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

  • 2. 2016/04/08 荒川 祐真 2 自己紹介 ● 名前: 荒川 祐真  →  大神 祐真 ● 仕事: 組み込み系のプログラマ ● 趣味: アーケードゲーム(古いシューティング系)、    OS自作(OS5) ● 最近よく使う言語(よく使うものから順に) – C言語、シェルスクリプト(言語?)、アセンブラ(x86)
  • 3. 2016/04/08 荒川 祐真 3 自己紹介 ● 名前: 荒川 祐真  →  大神 祐真 ● 仕事: 組み込み系のプログラマ ● 趣味: アーケードゲーム(古いシューティング系)、    OS自作(OS5) ● 最近よく使う言語(よく使うものから順に) – C言語、シェルスクリプト(言語?)、アセンブラ(x86) 本日の勉強会で 紹介
  • 4. 2016/04/08 荒川 祐真 4 今日お話する内容 1.はじめに 2.OS5の概観 3.カーネル 4.おわりに
  • 5. 2016/04/08 荒川 祐真 5 今日お話する内容 1.はじめに 2.OS5の概観 3.カーネル 4.おわりに 時間管理、タスク管理、 メモリ管理、ファイルシステム、 システムコール 各機能が どのように実装されてきたかを 見ていきます
  • 6. 2016/04/08 荒川 祐真 6 今日お話する内容 1.はじめに 2.OS5の概観 3.カーネル 4.おわりに
  • 7. 2016/04/08 荒川 祐真 7 OS5とは ● フルスクラッチ – OSについて理解したことの確認
  • 8. 2016/04/08 荒川 祐真 8 OS5とは ● フルスクラッチ – OSについて理解したことの確認 良くも悪くも、 オリジナルなOS
  • 9. 2016/04/08 荒川 祐真 9 OS5とは ● フルスクラッチ – OSについて理解したことの確認 ● まずはシンプルに – OS5の各機能(後述)は、 「そのとき必要な最小限」で実装 良くも悪くも、 オリジナルなOS
  • 10. 2016/04/08 荒川 祐真 10 今日お話する内容 1.はじめに 2.OS5の概観 3.カーネル 4.おわりに
  • 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. 2016/04/08 荒川 祐真 12 OS5でできること ● OS5はQEMU上で動作 ● MakeとGCCがあれば、 x86(32bit)マシン上でビルド可能 – x86(64bit)環境用には、 ビルド環境をQEMUイメージで公開中 OS5に関する情報は以下にまとめています http://funlinux.org/os5/
  • 13. 2016/04/08 荒川 祐真 13 コード行数の推移 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数
  • 14. 2016/04/08 荒川 祐真 14 コード行数の推移 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数 ブートローダー・カーネル・アプリ の総コード行数
  • 15. 2016/04/08 荒川 祐真 15 コード行数の推移 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数 ブートローダー : 253行 カーネル : 1966行 アプリケーション: 437行
  • 16. 2016/04/08 荒川 祐真 16 コード行数の推移 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数 ブートローダー : 253行 カーネル : 1966行 アプリケーション: 437行
  • 17. 2016/04/08 荒川 祐真 17 OS5カーネルのアーキテクチャ カーネル 時間 管理 ファイルシステム システムコール デバイスドライバ アプリ shell uptime コンソール CPU メモリ KBC CRTCPIT :機能の呼び出し関係 タスク管理 スケジューラ タスクローダ メモリ管理 ページング メモリアロケータ ソ フ ト ハ ー ド
  • 18. 2016/04/08 荒川 祐真 18 ブートローダーの概要 今回の主題はカーネルだが、 カーネルが起動するまでの流れとして ブートローダーを簡単に紹介
  • 19. 2016/04/08 荒川 祐真 19 ブートローダーの概要 PC 電源 ON
  • 20. 2016/04/08 荒川 祐真 20 ブートローダーの概要 PC 電源 ON BIOS
  • 21. 2016/04/08 荒川 祐真 21 ブートローダーの概要 PC 電源 ON BIOS ● Basic Input/Output System ● 起動デバイスのMBR(Master Boot Record、先頭512バイト) をRAMにロードし、CPUに実行させる
  • 22. 2016/04/08 荒川 祐真 22 ブートローダーの概要 PC 電源 ON BIOS ブート ローダー ● 512バイトに収まっており、MBR自体に相当 ● 以下を行う 1. モニターの画面モード設定 2. カーネルとアプリのバイナリをRAMへロード 3. CPUモードを16ビットから32ビットへ移行 4. RAMへロードしたカーネルを実行 ※ 1と2はBIOSの機能を利用する
  • 23. 2016/04/08 荒川 祐真 23 今日お話する内容 1.はじめに 2.OS5の概観 3.カーネル 4.おわりに
  • 24. 2016/04/08 荒川 祐真 24 コード行数の推移 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数
  • 25. 2016/04/08 荒川 祐真 25 コード行数の推移 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数 【主な追加機能】 ● ブートローダー ● アプリ(shell) ● デバイスドライバ(コンソール)
  • 26. 2016/04/08 荒川 祐真 26 コード行数の推移 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数 【主な追加機能】 ● ブートローダー ● アプリ(shell) ● デバイスドライバ(コンソール)
  • 27. 2016/04/08 荒川 祐真 27 OS5カーネルのアーキテクチャ デバイスドライバ shell コンソール CPU メモリ KBC CRTCPIT :機能の呼び出し関係 ソ フ ト ハ ー ド
  • 28. 2016/04/08 荒川 祐真 28 デバイスドライバとは ● ハードウェアを抽象化して、 利用しやすくする ● 現状のOS5カーネルでは、 「KBC(キーボードコントローラ)」と 「CRTC(CRTコントローラ)」を 「コンソール」として抽象化している デバイスドライバ コンソール KBC CRTC
  • 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. 2016/04/08 荒川 祐真 30 KBC i8042について ● キーボードやマウスを管理するための ワンチップ・マイコン ● キーボードやマウスにもワンチップ・マイコン が搭載されており、それらと相互に通信する
  • 31. 2016/04/08 荒川 祐真 31 制御用ICの使い方 ● in/out 命令を使用 ● 書式 – in ICの読み出すレジスタのアドレス, CPUの汎用レジスタ名 – out CPUの汎用レジスタ名, ICの書き込むレジスタのアドレス
  • 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. 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. 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. 2016/04/08 荒川 祐真 35 CRTC(MC6845)の使い方 1. ブートローダーで画面モードを設定 ➔ BIOSの機能を活用 2. カーネル起動後はVRAM領域への  データ書き込みで画面描画される ➔ VRAM領域: 0x000B 8000 〜 0x000B FFFF
  • 36. 2016/04/08 荒川 祐真 36 関連するソースコード ● os5/kernel/console_io.c ● os5/kernel/include/console_io.h
  • 37. 2016/04/08 荒川 祐真 37 コード行数の推移 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数 【主な追加機能】 ● 時間管理 ● タスク管理 (スケジューラによる マルチタスク) ● アプリ(uptime)
  • 38. 2016/04/08 荒川 祐真 38 コード行数の推移 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数 【主な追加機能】 ● 時間管理 ● タスク管理 (スケジューラによる マルチタスク) ● アプリ(uptime)
  • 39. 2016/04/08 荒川 祐真 39 OS5カーネルのアーキテクチャ 時間 管理 デバイスドライバ shell コンソール CPU メモリ KBC CRTCPIT :機能の呼び出し関係 ソ フ ト ハ ー ド
  • 40. 2016/04/08 荒川 祐真 40 時間管理について ● 役割 – 時間という単位の生成・管理・提供 ● やっていること – タイマー割り込み毎(10ms)に グローバルなカウンタ用変数をインクリメント ● 使用するハードウェア – PIT(Programmable Interval Timer) PIT
  • 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. 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. 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. 2016/04/08 荒川 祐真 44 PITの動作モード OS5カーネルではモード2に設定 0から作るOS開発 割り込みその3 PICのまとめとPITと割り込みハンドラ http://softwaretechnique.jp/OS_Development/kernel_development04.html カウンタ 割り込み 0x0000
  • 45. 2016/04/08 荒川 祐真 45 PITの動作モード OS5カーネルではモード2に設定 0から作るOS開発 割り込みその3 PICのまとめとPITと割り込みハンドラ http://softwaretechnique.jp/OS_Development/kernel_development04.html カウンタ 割り込み 0x2E9C カウンタに 値をセット
  • 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. 2016/04/08 荒川 祐真 47 PITの動作モード OS5カーネルではモード2に設定 0から作るOS開発 割り込みその3 PICのまとめとPITと割り込みハンドラ http://softwaretechnique.jp/OS_Development/kernel_development04.html カウンタ 割り込み 0x2E9C 0x0000
  • 48. 2016/04/08 荒川 祐真 48 PITの動作モード OS5カーネルではモード2に設定 0から作るOS開発 割り込みその3 PICのまとめとPITと割り込みハンドラ http://softwaretechnique.jp/OS_Development/kernel_development04.html カウンタ 割り込み 0x2E9C 0x0000 タイマー 割り込み
  • 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. 2016/04/08 荒川 祐真 50 PITの動作モード OS5カーネルではモード2に設定 0から作るOS開発 割り込みその3 PICのまとめとPITと割り込みハンドラ http://softwaretechnique.jp/OS_Development/kernel_development04.html カウンタ 割り込み 0x2E9C 0x0000
  • 51. 2016/04/08 荒川 祐真 51 PITの動作モード OS5カーネルではモード2に設定 0から作るOS開発 割り込みその3 PICのまとめとPITと割り込みハンドラ http://softwaretechnique.jp/OS_Development/kernel_development04.html カウンタ 割り込み 0x2E9C 0x0000
  • 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. 2016/04/08 荒川 祐真 53 実装 ● ソースコード – os5/kernel/timer.c – os5/kernel/include/timer.h
  • 54. 2016/04/08 荒川 祐真 54 コード行数の推移 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数 【主な追加機能】 ● 時間管理 ● タスク管理 (スケジューラによる マルチタスク) ● アプリ(uptime)
  • 55. 2016/04/08 荒川 祐真 55 OS5カーネルのアーキテクチャ カーネル 時間 管理 デバイスドライバ アプリ shell uptime コンソール CPU メモリ KBC CRTCPIT :機能の呼び出し関係 タスク管理 スケジューラ ソ フ ト ハ ー ド
  • 56. 2016/04/08 荒川 祐真 56 タスクとは? ● OS5のカーネル上で実行される処理の単位 ● 現状は、shellとuptimeの2つ ● 現状、タスク=アプリケーション – カーネル内のタスク管理で話をするときはタスク – カーネルより上位で話をするときはアプリケーション
  • 57. 2016/04/08 荒川 祐真 57 タスクの構造 タスクを管理する構造体: struct task os5/kernel/include/task.h
  • 58. 2016/04/08 荒川 祐真 58 タスクの構造 タスクを管理する構造体: struct task os5/kernel/include/task.h
  • 59. 2016/04/08 荒川 祐真 59 タスクの構造 タスクを管理する構造体: struct task os5/kernel/include/task.h 実行可能タスクを管理する 双方向リスト (ランキュー)
  • 60. 2016/04/08 荒川 祐真 60 タスクの構造 タスクを管理する構造体: struct task os5/kernel/include/task.h タスクを一意に決める ID
  • 61. 2016/04/08 荒川 祐真 61 タスクの構造 タスクを管理する構造体: struct task 以降のメンバは、 後ほど、登場する際に紹介
  • 62. 2016/04/08 荒川 祐真 62 マルチタスク 複数のタスクをちょっとずつ、 切り替えながら実行 shell uptime shell uptime shell uptime 時間
  • 63. 2016/04/08 荒川 祐真 63 マルチタスク 複数のタスクをちょっとずつ、 切り替えながら実行 shell uptime shell uptime shell uptime タイマー割り込み タイマー割り込み タイマー割り込み タイマー割り込み タイマー割り込み タイマー割り込み タイマー割り込み 10ms 時間
  • 64. 2016/04/08 荒川 祐真 64 マルチタスク 複数のタスクをちょっとずつ、 切り替えながら実行 shell uptime shell uptime shell uptime タイマー割り込み タイマー割り込み タイマー割り込み タイマー割り込み タイマー割り込み タイマー割り込み タイマー割り込み 10ms 時間 「タイムスライス」 と呼ぶ
  • 65. 2016/04/08 荒川 祐真 65 マルチタスク 複数のタスクをちょっとずつ、 切り替えながら実行 shell uptime shell uptime shell uptime タイマー割り込み タイマー割り込み タイマー割り込み タイマー割り込み タイマー割り込み タイマー割り込み タイマー割り込み 10ms スケジューラは いわば、 CPUの計算資源の 管理 時間
  • 66. 2016/04/08 荒川 祐真 66 マルチタスク 複数のタスクをちょっとずつ、 切り替えながら実行 shell uptime shell uptime shell uptime タイマー割り込み タイマー割り込み タイマー割り込み タイマー割り込み タイマー割り込み タイマー割り込み タイマー割り込み 10ms スケジューラは いわば、 CPUの計算資源の 管理 時間 「コンテキストスイッチ」 と呼ぶ
  • 67. 2016/04/08 荒川 祐真 67 コンテキストスイッチの流れ shell uptime 現在 実行中の タスク ランキュー struct task
  • 68. 2016/04/08 荒川 祐真 68 コンテキストスイッチの流れ shell uptime 現在 実行中の タスク ランキュー コンテキストスイッチ イベント 発生
  • 69. 2016/04/08 荒川 祐真 69 コンテキストスイッチの流れ shell uptime 現在 実行中の タスク ランキュー タスク管理 スケジューラ スケジューラは 次に実行するタスクを 選択 次に 実行する タスク
  • 70. 2016/04/08 荒川 祐真 70 コンテキストスイッチの流れ shell uptime 現在 実行中の タスク ランキュー タスク管理 スケジューラ 次に 実行する タスク コンテキストスイッチ
  • 71. 2016/04/08 荒川 祐真 71 コンテキストスイッチに必要なこと 今までshellを実行していたCPUを uptimeへスイッチするには 1.shellを再開するときのために、 情報を退避 2.退避していたuptimeの情報を 復帰 3.uptimeを再開
  • 72. 2016/04/08 荒川 祐真 72 コンテキストスイッチに必要なこと 今までshellを実行していたCPUを uptimeへスイッチするには 1.shellを再開するときのために、 情報を退避 2.退避していたuptimeの情報を 復帰 3.uptimeを再開 このような情報をコンテキストと呼ぶ コンテキストに含まれるもの ● IP(インストラクションポインタ) ● フラグレジスタ ● スタックポインタ ● 汎用レジスタ
  • 73. 2016/04/08 荒川 祐真 73 コンテキストスイッチに必要なこと 今までshellを実行していたCPUを uptimeへスイッチするには 1.shellを再開するときのために、 情報を退避 2.退避していたuptimeの情報を 復帰 3.uptimeを再開
  • 74. 2016/04/08 荒川 祐真 74 コンテキストスイッチに必要なこと 今までshellを実行していたCPUを uptimeへスイッチするには 1.shellを再開するときのために、 情報を退避 2.退避していたuptimeの情報を 復帰 3.uptimeを再開 x86 CPUの タスク機能を 活用
  • 75. 2016/04/08 荒川 祐真 75 x86のタスク機能 ● x86のCPUはタスクを管理する構造と機能を 持っている ● やってくれること – 命令1つで 1. 実行中タスクの退避 2. 次に実行するタスクの復帰 3. 実行再開 を行ってくれる
  • 76. 2016/04/08 荒川 祐真 76 x86のタスク機能 ● x86のCPUはタスクを管理する構造と機能を 持っている ● やってくれること – 命令1つで 1. 実行中タスクの退避 2. 次に実行するタスクの復帰 3. 実行再開 を行ってくれる jmp TSSのアドレス
  • 77. 2016/04/08 荒川 祐真 77 x86のタスク機能 ● x86のCPUはタスクを管理する構造と機能を 持っている ● やってくれること – 命令1つで 1. 実行中タスクの退避 2. 次に実行するタスクの復帰 3. 実行再開 を行ってくれる jmp TSSのアドレス 【TSS】 Task State Segment タスクの退避/復帰で 使用する領域
  • 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. 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. 2016/04/08 荒川 祐真 80 タスクの構造 タスクを管理する構造体: struct task
  • 81. 2016/04/08 荒川 祐真 81 関連するソースコード ● スケジューラ – os5/kernel/sched.c – os5/kernel/include/sched.h ● タスク – os5/kernel/task.c – os5/kernel/include/task.h
  • 82. 2016/04/08 荒川 祐真 82 コード行数の推移 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数 【主な追加機能】 ● メモリ管理 (ページング)
  • 83. 2016/04/08 荒川 祐真 83 コード行数の推移 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数 【主な追加機能】 ● メモリ管理 (ページング)
  • 84. 2016/04/08 荒川 祐真 84 カーネル 時間 管理 デバイスドライバ アプリ shell uptime コンソール CPU メモリ KBC CRTCPIT :機能の呼び出し関係 タスク管理 スケジューラ メモリ管理 ページング ソ フ ト ハ ー ド OS5カーネルのアーキテクチャ
  • 85. 2016/04/08 荒川 祐真 85 OS5の現在のメモリマップ 物理アドレス空間 0x0000 0000 0xFFFF FFFF
  • 86. 2016/04/08 荒川 祐真 86 OS5の現在のメモリマップ 物理アドレス空間 0x0000 0000 0xFFFF FFFF
  • 87. 2016/04/08 荒川 祐真 87 OS5の現在のメモリマップ 物理アドレス空間 0x0000 0000 0xFFFF FFFF コンベンショナルメモリ領域 (640KB) 0x0000 0500 〜 0x0009 FFFF
  • 88. 2016/04/08 荒川 祐真 88 OS5の現在のメモリマップ コンベンショナルメモリ 0x0000 0500 0x0009 FFFF OS5は現在、 このコンベンショナルメモリの領域 を想定し、動作している
  • 89. 2016/04/08 荒川 祐真 89 OS5の現在のメモリマップ コンベンショナルメモリ 0x0000 0500 0x0009 FFFF カーネルバイナリ配置領域 (36.5KB) 0x0000 7E00 〜 0x0001 0FFF ユーザーランド配置領域 (12.0KB) 0x0001 1000 〜 0x0001 3FFF
  • 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. 2016/04/08 荒川 祐真 91 OS5の現在のメモリマップ コンベンショナルメモリ 0x0000 0500 0x0009 FFFF カーネルスタック領域 (436.0KB) 0x0001 3000 〜 0x0007 FFFF カーネル用ページテーブル配置領域 (8.0KB) 0x0008 F000 〜 0x0009 0FFF 0x0008 0000
  • 92. 2016/04/08 荒川 祐真 92 OS5の現在のメモリマップ コンベンショナルメモリ 0x0000 0500 0x0009 FFFF ヒープ領域 (44.0KB) 0x0009 5000 〜 0x0009 FFFF 0x0008 0000
  • 93. 2016/04/08 荒川 祐真 93 ページングとは? 物理アドレス空間を固定長(4KB)毎に分割 それぞれに、物理アドレスとは別のアドレス (仮想アドレス)を割り当て、 メモリを管理する仕組み
  • 94. 2016/04/08 荒川 祐真 94 ページングとは? 物理アドレス空間 ※ 表示の都合上、   コンベンショナルメモリ領域を   拡大 0x0000 0500 0x0009 FFFF 0x0008 0000
  • 95. 2016/04/08 荒川 祐真 95 ページングとは? 物理アドレス空間 ※ 表示の都合上、   コンベンショナルメモリ領域を   拡大 0x0000 0500 0x0009 FFFF 0x0008 0000 ユーザーランド配置領域 (12.0KB) 0x0001 1000 〜 0x0001 3FFF
  • 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. 2016/04/08 荒川 祐真 97 ページングとは? 物理アドレス空間 ※ 表示の都合上、   ユーザーランド領域を   拡大 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 物理アドレス空間全体 (0x0000 0000 〜 0xFFFF FFFF)を、 4KB単位で分割 分割した 各4KBの領域を 「ページ」と呼ぶ
  • 98. 2016/04/08 荒川 祐真 98 ページングとは? 物理アドレス空間 ※ 表示の都合上、   ユーザーランド領域を   拡大 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 仮想アドレス(VA)を 物理アドレス(PA)へ変換する 変換表を用意 VA PA 0x2000 0000 0x0001 2000
  • 99. 2016/04/08 荒川 祐真 99 ページングとは? 物理アドレス空間 ※ 表示の都合上、   ユーザーランド領域を   拡大 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 仮想アドレス(VA)を 物理アドレス(PA)へ変換する 変換表を用意 VA PA 0x2000 0000 0x0001 2000 ※ ちなみに、VAにPAを対応付けることを、   「マップする」と言う
  • 100. 2016/04/08 荒川 祐真 100 ページングとは? 物理アドレス空間 ※ 表示の都合上、   ユーザーランド領域を   拡大 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 ページング有効化! VA PA 0x2000 0000 0x0001 2000 MMU 【Memory Management Unit】 アドレス変換を行ってくれる ハードウェア
  • 101. 2016/04/08 荒川 祐真 101 ページングとは? 物理アドレス空間 ※ 表示の都合上、   ユーザーランド領域を   拡大 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 CPUはMMUを介して メモリアクセス VA PA 0x2000 0000 0x0001 2000 MMU
  • 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. 2016/04/08 荒川 祐真 103 ページングとは? 物理アドレス空間 ※ 表示の都合上、   ユーザーランド領域を   拡大 0x0001 1000 0x0001 3FFF = 0x0001 2000 0x0001 3000 MMUは CPUがアクセスするアドレス(VA)を PAに変換 VA PA 0x2000 0000 0x0001 2000 MMU
  • 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. 2016/04/08 荒川 祐真 105 仮想アドレス空間のメモリマップ 0x0000 0000 0xFFFF FFFF カーネル 空間 ユーザ 空間 0x2000 0000 仮 想 ア ド レ ス 空 間 コンベンショナル メモリ領域 物 理 ア ド レ ス 空 間
  • 106. 2016/04/08 荒川 祐真 106 仮想アドレス空間のメモリマップ 0x0000 0000 0xFFFF FFFF カーネル 空間 ユーザ 空間 0x2000 0000 仮 想 ア ド レ ス 空 間 コンベンショナル メモリ領域 物 理 ア ド レ ス 空 間 VA=PA カーネル空間から 全ての資源にアクセス可
  • 107. 2016/04/08 荒川 祐真 107 仮想アドレス空間のメモリマップ 0x0000 0000 0xFFFF FFFF カーネル 空間 ユーザ 空間 0x2000 0000 仮 想 ア ド レ ス 空 間 物 理 ア ド レ ス 空 間 shell uptime VAは 現在実行中のタスクに マップされる (この場合shell)
  • 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. 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. 2016/04/08 荒川 祐真 110 shellとuptimeのPD・PTについて ページテーブルページディレクトリ ページ カーネル shell uptime shell用 uptime用 shell用 uptime用 カーネル用
  • 111. 2016/04/08 荒川 祐真 111 shellとuptimeのPD・PTについて ページテーブルページディレクトリ ページ カーネル shell uptime shell用 uptime用 shell用 uptime用 カーネル用 共通のPTを使用
  • 112. 2016/04/08 荒川 祐真 112 shellとuptimeのPD・PTについて ページテーブルページディレクトリ ページ カーネル shell uptime shell用 uptime用 shell用 uptime用 カーネル用 タスク毎のPD切り替えも コンテキストスイッチ時に CPUが自動で行う
  • 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. 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. 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. 2016/04/08 荒川 祐真 116 関連するソースコード ● os5/kernel/memory.c ● os5/kernel/include/memory.h
  • 117. 2016/04/08 荒川 祐真 117 OS5の機能構成(ソースコード構成) 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数 【主な追加機能】 ● タスク管理 (スケジューラによる タスクスリープ/ウェイクアップ) ● 省電力機能 ● 特権管理 ● システムコール
  • 118. 2016/04/08 荒川 祐真 118 OS5の機能構成(ソースコード構成) 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数 【主な追加機能】 ● タスク管理 (スケジューラによる タスクスリープ/ウェイクアップ) ● 省電力機能 ● 特権管理 ● システムコール
  • 119. 2016/04/08 荒川 祐真 119 カーネル 時間 管理 デバイスドライバ アプリ shell uptime コンソール CPU メモリ KBC CRTCPIT :機能の呼び出し関係 タスク管理 スケジューラ メモリ管理 ページング ソ フ ト ハ ー ド OS5カーネルのアーキテクチャ
  • 120. 2016/04/08 荒川 祐真 120 タスクのスリープについて ● タスクだって寝たい時がある – 「XX分後に起こしてー」 – 「XXがあったら起こしてー」
  • 121. 2016/04/08 荒川 祐真 121 タスクのスリープについて ● タスクだって寝たい時がある – 「XX分後に起こしてー」 – 「XXがあったら起こしてー」 OS5では、タスクについて、以下を登録できる ・ウェイクアップタイマー ・ウェイクアップイベント
  • 122. 2016/04/08 荒川 祐真 122 タスクのスリープについて ● ウェイクアップタイマー(目覚し時計) – 関数: wakeup_after_msec(unsigned int msec) – 「XXms後に起こしてー」 ● ウェイクアップイベント(目覚ましイベント) – 関数: wakeup_after_event(unsigned char event_type) – 「XXが起きたら起こしてー」 – 今、対応しているイベントは「キーボード入力」のみ
  • 123. 2016/04/08 荒川 祐真 123 タスクのスリープについて どのように実現しているのか?
  • 124. 2016/04/08 荒川 祐真 124 タスクのスリープについて どのように実現しているのか? ランキューから抜いたり追加したりする
  • 125. 2016/04/08 荒川 祐真 125 タスクのスリープについて どのように実現しているのか? ランキュー shell uptime
  • 126. 2016/04/08 荒川 祐真 126 タスクのスリープについて どのように実現しているのか? ランキュー shell uptime 33ms後に 起こしてー ※ タイマー割り込みの粒度が10msなので、   実際は40ms後に起こされる
  • 127. 2016/04/08 荒川 祐真 127 タスクのスリープについて どのように実現しているのか? ランキュー shell uptime ウェイクアップキュー
  • 128. 2016/04/08 荒川 祐真 128 タスクのスリープについて どのように実現しているのか? ランキュー shell uptime ウェイクアップキュー 以降、shellのみ実行
  • 129. 2016/04/08 荒川 祐真 129 タスクのスリープについて どのように実現しているのか? ランキュー shell uptime ウェイクアップキュー タイマー割り込み発生 33ms以上経過
  • 130. 2016/04/08 荒川 祐真 130 タスクのスリープについて どのように実現しているのか? ランキュー shell uptime ウェイクアップキュー ランキューに戻す
  • 131. 2016/04/08 荒川 祐真 131 タスクの構造 タスクを管理する構造体: struct task ウェイクアップキュー への追加時の ウェイクアップ要因 管理用 unsigned int wakeup_after_msec; unsigned char wakeup_after_event;
  • 132. 2016/04/08 荒川 祐真 132 スリープでのコンテキストスイッチ による問題 時間 10ms 10ms 10ms タイマー割り込み によるコンテキストスイッチ
  • 133. 2016/04/08 荒川 祐真 133 時間 10ms 10ms 10ms shell キー入力待ち スリープでのコンテキストスイッチ による問題
  • 134. 2016/04/08 荒川 祐真 134 時間 10ms 10ms 10ms shell uptime ちょっとしか 実行できない・・・ スリープでのコンテキストスイッチ による問題
  • 135. 2016/04/08 荒川 祐真 135 ● 自らスリープした時は、 「タイムスライスの残りを他タスクにプレゼント」と判断 時間 10ms 10ms 10ms shell uptime uptime スリープでのコンテキストスイッチ による問題
  • 136. 2016/04/08 荒川 祐真 136 タスクの構造 タスクを管理する構造体: struct task コンテキストスイッチ時、 タイムスライスを 使い切ったか否かの 判別用 char task_switched_in_time_slice;
  • 137. 2016/04/08 荒川 祐真 137 OS5の機能構成(ソースコード構成) 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数 【主な追加機能】 ● タスク管理 (スケジューラによる タスクスリープ/ウェイクアップ) ● 省電力機能 ● 特権管理 ● システムコール
  • 138. 2016/04/08 荒川 祐真 138 カーネル 時間 管理 デバイスドライバ アプリ shell uptime コンソール CPU メモリ KBC CRTCPIT :機能の呼び出し関係 タスク管理 スケジューラ メモリ管理 ページング ソ フ ト ハ ー ド OS5カーネルのアーキテクチャ
  • 139. 2016/04/08 荒川 祐真 139 カーネルタスク ● 省電力機能 ランキューに何も無いときには、カーネルタスクを実行 ランキュー 空 カーネル タスク
  • 140. 2016/04/08 荒川 祐真 140 カーネルタスク ● 省電力機能 ランキューに何も無いときには、カーネルタスクを実行 ランキュー 空 カーネル タスク hlt命令を実行 割り込みがあるまで CPUを休ませる
  • 141. 2016/04/08 荒川 祐真 141 関連するソースコード ● カーネルタスク – os5/kernel/kern_task_init.c – os5/kernel/include/kern_task.h ● カーネル初期化 – os5/kernel/init.c
  • 142. 2016/04/08 荒川 祐真 142 関連するソースコード ● カーネルタスク – os5/kernel/kern_task_init.c – os5/kernel/include/kern_task.h ● カーネル初期化 – os5/kernel/init.c
  • 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. 2016/04/08 荒川 祐真 144 コード行数の推移 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数 【主な追加機能】 ● タスク管理 (スケジューラによる タスクスリープ/ウェイクアップ) ● 省電力機能 ● 特権管理 ● システムコール
  • 145. 2016/04/08 荒川 祐真 145 カーネル 時間 管理 デバイスドライバ アプリ shell uptime コンソール CPU メモリ KBC CRTCPIT :機能の呼び出し関係 タスク管理 スケジューラ メモリ管理 ページング ソ フ ト ハ ー ド OS5カーネルのアーキテクチャ
  • 146. 2016/04/08 荒川 祐真 146 x86 CPUの特権レベル ● x86 CPUには0〜3の4つの特権レベルがある – 番号が大きくなると、特権が低くなる ● OS5カーネルでは0と3の特権レベルを使用 – カーネル: 特権レベル0 – タスク : 特権レベル3 ● 特権レベルは、 TSSを定義するセグメントディスクリプタに設定
  • 147. 2016/04/08 荒川 祐真 147 x86 CPUの特権レベル ● x86 CPUには0〜3の4つの特権レベルがある – 番号が大きくなると、特権が低くなる ● OS5カーネルでは0と3の特権レベルを使用 – カーネル: 特権レベル0 – タスク : 特権レベル3 ● 特権レベルは、 TSSを定義するセグメントディスクリプタに設定
  • 148. 2016/04/08 荒川 祐真 148 そもそも、「セグメント」とは 【セグメンテーション】 ● アドレス空間を「ベースアドレス」と「リミット」で分割し、 管理する方式 ● 分割した領域を「セグメント」と呼ぶ
  • 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. 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. 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. 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. 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. 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. 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. 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. 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. 2016/04/08 荒川 祐真 158 コード行数の推移 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数 【主な追加機能】 ● タスク管理 (スケジューラによる タスクスリープ/ウェイクアップ) ● 省電力機能 ● 特権管理 ● システムコール
  • 159. 2016/04/08 荒川 祐真 159 カーネル 時間 管理 システムコール デバイスドライバ アプリ shell uptime コンソール CPU メモリ KBC CRTCPIT :機能の呼び出し関係 タスク管理 スケジューラ メモリ管理 ページング ソ フ ト ハ ー ド OS5カーネルのアーキテクチャ
  • 160. 2016/04/08 荒川 祐真 160 システムコールとは ● OS5において、 アプリケーションがカーネルとやり取りする ための唯一のインタフェース
  • 161. 2016/04/08 荒川 祐真 161 実装 ● アプリケーションは ユーザーの特権レベルで動作 ● カーネル空間の関数を呼ぶことはできない ● カーネル空間の機能を呼び出すために、 「ソフトウェア割り込み」を使用
  • 162. 2016/04/08 荒川 祐真 162 動作例 shell kernel 3 現在の特権レベル EAX EBX ECX EDX 汎用レジスタ
  • 163. 2016/04/08 荒川 祐真 163 動作例 shell kernel 3 現在の特権レベル EAX EBX ECX EDX 汎用レジスタ shell動作中
  • 164. 2016/04/08 荒川 祐真 164 動作例 shell kernel 3 現在の特権レベル EAX EBX ECX EDX 汎用レジスタ “Hello”と 画面に表示したい
  • 165. 2016/04/08 荒川 祐真 165 動作例 shell kernel 3 現在の特権レベル EAX EBX ECX EDX 汎用レジスタ CON_PUT_STR システムコール (文字列をコンソール上に 出力するシステムコール) を実行したい
  • 166. 2016/04/08 荒川 祐真 166 動作例 shell kernel 3 現在の特権レベル EAX EBX ECX EDX 汎用レジスタ 【前提条件】 アプリケーションとカーネルの間で、 以下の合意が取れている ● システムコールに使用する割り込み番号 ● 汎用レジスタを使用した値受け渡し方法
  • 167. 2016/04/08 荒川 祐真 167 動作例 shell kernel 3 現在の特権レベル CON_PUT_STR(定数)EAX “Hello”の先頭アドレスEBX ECX EDX 汎用レジスタ EAXにシステムコールIDを、 EBX〜EDXに第1〜第3引数を設定
  • 168. 2016/04/08 荒川 祐真 168 動作例 shell kernel 3 現在の特権レベル CON_PUT_STR(定数)EAX “Hello”の先頭アドレスEBX ECX EDX 汎用レジスタ int $0x80 ソフトウェア割り込み実行 ※ OS5カーネルでは、0x80番のソフトウェア割り込みを  システムコールとして使用する
  • 169. 2016/04/08 荒川 祐真 169 動作例 shell kernel 0 現在の特権レベル CON_PUT_STR(定数)EAX “Hello”の先頭アドレスEBX ECX EDX 汎用レジスタ 特権レベル昇格 0x80番の割り込みハンドラ が呼び出される
  • 170. 2016/04/08 荒川 祐真 170 動作例 shell kernel 0 現在の特権レベル CON_PUT_STR(定数)EAX “Hello”の先頭アドレスEBX ECX EDX 汎用レジスタ 割り込みハンドラ内で 以下を実行 1. EAXで対象の  システムコールを確認 2. システムコールに対応  するカーネル内の関数  を実行 3. 戻り値をEAXに設定 4. 割り込みからリターン
  • 171. 2016/04/08 荒川 祐真 171 動作例 shell kernel 3 現在の特権レベル CON_PUT_STR(定数)EAX “Hello”の先頭アドレスEBX ECX EDX 汎用レジスタ 元の特権レベルに戻る
  • 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. 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. 2016/04/08 荒川 祐真 174 関連するソースコード ● os5/kernel/sys.S ● os5/kernel/syscall.c ● os5/kernel/include/syscall.h
  • 175. 2016/04/08 荒川 祐真 175 コード行数の推移 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数 【主な追加機能】 ● ファイルシステム ● メモリ管理 (メモリアロケータ) ● タスク管理 (タスクローダ)
  • 176. 2016/04/08 荒川 祐真 176 コード行数の推移 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数 【主な追加機能】 ● ファイルシステム ● メモリ管理 (メモリアロケータ) ● タスク管理 (タスクローダ)
  • 177. 2016/04/08 荒川 祐真 177 カーネル 時間 管理 ファイルシステム システムコール デバイスドライバ アプリ shell uptime コンソール CPU メモリ KBC CRTCPIT :機能の呼び出し関係 タスク管理 スケジューラ メモリ管理 ページング ソ フ ト ハ ー ド OS5カーネルのアーキテクチャ
  • 178. 2016/04/08 荒川 祐真 178 なんのためのもの? ● 単なるバイナリ列を、 「ファイル」として扱うためのルール決め ● OS5の場合、全てのデータは、 ブートローダーがRAMにロードする ● RAM上の「ユーザーランド領域」の バイナリ列のルールを決めている
  • 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. 2016/04/08 荒川 祐真 180 OS5の現在のファイルシステム ユーザーランド領域 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 【ルール1】 先頭4KBにコントロールブロックを 配置
  • 181. 2016/04/08 荒川 祐真 181 OS5の現在のファイルシステム ユーザーランド領域 0x0001 1000 0x0001 3FFF 2 0x0001 2000 0x0001 3000 【ルール2】 コントロールブロックには 存在するファイル数を格納
  • 182. 2016/04/08 荒川 祐真 182 OS5の現在のファイルシステム ユーザーランド領域 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 【ルール3】 ファイルは4KB以内 4KB 4KB
  • 183. 2016/04/08 荒川 祐真 183 OS5の現在のファイルシステム ユーザーランド領域 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 【ルール4】 ファイルの先頭32バイトに ファイル名を格納 shell uptime
  • 184. 2016/04/08 荒川 祐真 184 OS5の現在のファイルシステム ユーザーランド領域 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 【ルール5】 ファイルの先頭33バイト以降に ファイル本体を格納 ファイル本体を 配置
  • 185. 2016/04/08 荒川 祐真 185 OS5の現在のファイルシステム ユーザーランド領域 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 【ルール6】 ファイルを実行する際は、 先頭33バイト目にジャンプする
  • 186. 2016/04/08 荒川 祐真 186 OS5の現在のファイルシステム ユーザーランド領域 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 【ルール6】 ファイルを実行する際は、 先頭33バイト目にジャンプする os5/apps/app.lc
  • 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. 2016/04/08 荒川 祐真 188 OS5の現在のファイルシステム ユーザーランド領域 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 【ルール6】 ファイルを実行する際は、 先頭33バイト目にジャンプする os5/apps/app.lc textセクション (コンパイル結果の機械語を 配置するセクション)を 先頭に配置
  • 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. 2016/04/08 荒川 祐真 190 OS5の現在のファイルシステム ユーザーランド領域 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 【ルール6】 ファイルを実行する際は、 先頭33バイト目にジャンプする TSSの一部 EIP
  • 191. 2016/04/08 荒川 祐真 191 OS5の現在のファイルシステム ユーザーランド領域 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 【ルール6】 ファイルを実行する際は、 先頭33バイト目にジャンプする TSSの一部 EIP タスク初期化時、 EIPに 0x2000 0020 を設定
  • 192. 2016/04/08 荒川 祐真 192 ファイルの構造 ファイルを管理する構造体: struct file
  • 193. 2016/04/08 荒川 祐真 193 ファイルの構造 ファイルを管理する構造体: struct file
  • 194. 2016/04/08 荒川 祐真 194 ファイルシステムの初期化 ファイルシステム内を検索し、 struct fileのリンクリストを作成 0x0001 1000 0x0001 3FFF 0x0001 2000 0x0001 3000 shell uptime
  • 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. 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. 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. 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. 2016/04/08 荒川 祐真 199 関連するソースコード ● os5/kernel/fs.c ● os5/kernel/include/fs.h ● os5/tools/make_os5_fs.sh – アプリケーションバイナリから ファイルシステムを生成する シェルスクリプト
  • 200. 2016/04/08 荒川 祐真 200 コード行数の推移 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数 【主な追加機能】 ● ファイルシステム ● メモリ管理 (メモリアロケータ) ● タスク管理 (タスクローダ)
  • 201. 2016/04/08 荒川 祐真 201 カーネル 時間 管理 ファイルシステム システムコール デバイスドライバ アプリ shell uptime コンソール CPU メモリ KBC CRTCPIT :機能の呼び出し関係 タスク管理 スケジューラ メモリ管理 ページング メモリアロケータ ソ フ ト ハ ー ド OS5カーネルのアーキテクチャ
  • 202. 2016/04/08 荒川 祐真 202 メモリアロケータ ● どのようなものか? – メモリ上にヒープ領域を設定 – メモリの動的確保を要求された時、 ヒープ領域からメモリを確保し、要求者へ与える ● OS5の場合、固定長(4KB) – ヒープ領域内の使用状況の管理も行う
  • 203. 2016/04/08 荒川 祐真 203 メモリアロケータ コンベンショナルメモリ 0x0000 0500 0x0009 FFFF ヒープ領域 (44.0KB) 0x0009 5000 〜 0x0009 FFFF 0x0008 0000
  • 204. 2016/04/08 荒川 祐真 204 メモリアロケータ ヒープ領域 0x0009 5000 0x0009 FFFF
  • 205. 2016/04/08 荒川 祐真 205 メモリアロケータ ヒープ領域 0x0009 5000 0x0009 FFFF 固定長(4KB)で分割
  • 206. 2016/04/08 荒川 祐真 206 メモリアロケータ ヒープ領域 0x0009 5000 0x0009 FFFF メモリ動的確保の要求があれば、 4KBずつ与える タスク管理 uptimeタスク用に スタック領域を 確保したい
  • 207. 2016/04/08 荒川 祐真 207 メモリアロケータ ヒープ領域 0x0009 5000 0x0009 FFFF メモリ動的確保の要求があれば、 4KBずつ与える タスク管理 メモリちょうだい mem_alloc() メモリ アロケータ
  • 208. 2016/04/08 荒川 祐真 208 メモリアロケータ ヒープ領域 0x0009 5000 0x0009 FFFF メモリ動的確保の要求があれば、 4KBずつ与える タスク管理 メモリ アロケータ 使ってないヤツ 見つけた!
  • 209. 2016/04/08 荒川 祐真 209 メモリアロケータ ヒープ領域 0x0009 5000 0x0009 FFFF メモリ動的確保の要求があれば、 4KBずつ与える タスク管理 メモリ アロケータ 使用中の目印を 付けておこう
  • 210. 2016/04/08 荒川 祐真 210 メモリアロケータ ヒープ領域 0x0009 5000 0x0009 FFFF メモリ動的確保の要求があれば、 4KBずつ与える タスク管理 メモリ アロケータ 使用中の目印を 付けておこう heap_alloc_table という配列で管理
  • 211. 2016/04/08 荒川 祐真 211 メモリアロケータ ヒープ領域 0x0009 5000 0x0009 FFFF メモリ動的確保の要求があれば、 4KBずつ与える タスク管理 メモリ アロケータ 確保できたよ 0x0009 5000
  • 212. 2016/04/08 荒川 祐真 212 メモリアロケータ ヒープ領域 0x0009 5000 0x0009 FFFF メモリ動的確保の要求があれば、 4KBずつ与える タスク管理 メモリ アロケータ 0x0009 5000から 4KBの領域を uptimeのスタックに使おう
  • 213. 2016/04/08 荒川 祐真 213 コード行数の推移 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08 日付(ブログ記事投稿) 総 コード 行数 【主な追加機能】 ● ファイルシステム ● メモリ管理 (メモリアロケータ) ● タスク管理 (タスクローダ)
  • 214. 2016/04/08 荒川 祐真 214 カーネル 時間 管理 ファイルシステム システムコール デバイスドライバ アプリ shell uptime コンソール CPU メモリ KBC CRTCPIT :機能の呼び出し関係 タスク管理 スケジューラ タスクローダ メモリ管理 ページング メモリアロケータ ソ フ ト ハ ー ド OS5カーネルのアーキテクチャ
  • 215. 2016/04/08 荒川 祐真 215 タスクローダとは ● 役割 1.ファイルシステム上からファイルを見つける 2.新たなタスクのためのメモリを確保 3.タスクの構造を用意し、初期化
  • 216. 2016/04/08 荒川 祐真 216 タスクローダとは ● 役割 1.ファイルシステム上からファイルを見つける 2.新たなタスクのためのメモリを確保 3.タスクの構造を用意し、初期化 ファイルシステム
  • 217. 2016/04/08 荒川 祐真 217 タスクローダとは ● 役割 1.ファイルシステム上からファイルを見つける 2.新たなタスクのためのメモリを確保 3.タスクの構造を用意し、初期化 ファイルシステム メモリ管理
  • 218. 2016/04/08 荒川 祐真 218 タスクローダとは ● 役割 1.ファイルシステム上からファイルを見つける 2.新たなタスクのためのメモリを確保 3.タスクの構造を用意し、初期化 ファイルシステム メモリ管理 タスク管理
  • 219. 2016/04/08 荒川 祐真 219 タスクローダとは ● 役割 1.ファイルシステム上からファイルを見つける 2.新たなタスクのためのメモリを確保 3.タスクの構造を用意し、初期化 ファイルシステム メモリ管理 タスク管理 カーネルの複数の機能の集大成
  • 220. 2016/04/08 荒川 祐真 220 タスクの生成 ● タスクを生成する際は、 以下の領域のためのメモリを動的に確保し、 それぞれ初期化する – TSS – スタック領域 – ページディレクトリ・ページテーブル
  • 221. 2016/04/08 荒川 祐真 221 タスクの初期化 os5/kernel/task.c の task_init 関数の動作を見てみる
  • 222. 2016/04/08 荒川 祐真 222 タスクの初期化 ① 引数でstruct fileのポインタを受け取る struct listuptimeの struct file next prev char *name void *data_base_addr
  • 223. 2016/04/08 荒川 祐真 223 タスクの初期化 ② タスク作成に必要なメモリを動的確保 struct listuptimeの struct file next prev char *name void *data_base_addr PD用 PT用 struct task用 スタック用
  • 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. 2016/04/08 荒川 祐真 225 タスクの初期化 ④ タスクIDを作成・設定 struct listuptimeの struct file next prev char *name void *data_base_addr struct task用 スタック用
  • 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. 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. 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. 2016/04/08 荒川 祐真 229 タスクの構造 タスクを管理する構造体: struct task
  • 230. 2016/04/08 荒川 祐真 230 タスクの構造 タスクを管理する構造体: struct task void (*context_switch)(void); unsigned char context_switch_func[CONTEXT_SWITCH_FN_SIZE]
  • 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. 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. 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. 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. 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. 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. 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. 2016/04/08 荒川 祐真 238 【再掲】OS5の現在のメモリマップ コンベンショナルメモリ 0x0000 0500 0x0009 FFFF カーネルスタック領域 (436.0KB) 0x0001 3000 〜 0x0007 FFFF 0x0008 0000カーネルスタックの ベースアドレス
  • 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. 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. 2016/04/08 荒川 祐真 241 今日お話する内容 1.はじめに 2.OS5の概観 3.カーネル 4.おわりに
  • 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. 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. 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. 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. 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. 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. 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. 2016/04/08 荒川 祐真 249 ご清聴ありがとうございました
  • 250. 2016/04/08 荒川 祐真 250 以降、付録です 時間の関係で割愛した説明や、 別の言い方での説明など 参考までに残しておきます
  • 251. 2016/04/08 荒川 祐真 251 現状のブートローダーについて ● ハードウェアをセットアップし、 カーネルの先頭アドレスへジャンプする ● MBRの512バイトそのもの – 0x0000 7c00 〜 0x0000 7dff ● 現状は、全てアセンブラで記述
  • 252. 2016/04/08 荒川 祐真 252 現状のブートローダーについて ● ハードウェアをセットアップし、 カーネルの先頭アドレスへジャンプする 少しブレークダウン 1. BIOS割り込みルーチンで ハードウェア初期化とRAMへのロード 2. CPUのモード変更 3. カーネルの先頭アドレスへジャンプ
  • 253. 2016/04/08 荒川 祐真 253 現状のブートローダーについて ● ハードウェアをセットアップし、 カーネルの先頭アドレスへジャンプする 少しブレークダウン 1. BIOS割り込みルーチンで ハードウェア初期化とRAMへのロード 2. CPUのモード変更 3. カーネルの先頭アドレスへジャンプ
  • 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. 2016/04/08 荒川 祐真 255 現状のブートローダーについて ● ハードウェアをセットアップし、 カーネルの先頭アドレスへジャンプする 少しブレークダウン 1. BIOS割り込みルーチンで ハードウェア初期化とRAMへのロード 2. CPUのモード変更 3. カーネルの先頭アドレスへジャンプ
  • 256. 2016/04/08 荒川 祐真 256 現状のブートローダーについて ● ハードウェアをセットアップし、 カーネルの先頭アドレスへジャンプする 少しブレークダウン 1. BIOS割り込みルーチンで ハードウェア初期化とRAMへのロード 2. CPUのモード変更 3. カーネルの先頭アドレスへジャンプ 16ビット → 32ビット
  • 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. 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. 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. 2016/04/08 荒川 祐真 260 ページングとは? ● 仮想記憶(仮想メモリ)を実現する方式 ● メモリを「ページ」という単位で分割して管理する RAM アーキテクチャにもよるが、 OS5やLinux(x86)では4KB ページ
  • 261. 2016/04/08 荒川 祐真 261 ページングとは? ● 複数のタスクを同時に実行する際、実行時に必要なページ のみロード RAM TaskA TaskB ページイン HDDなどの補助記憶 ページアウト
  • 262. 2016/04/08 荒川 祐真 262 OS5でのページング ● とはいえ、OS5においてはカーネル・アプリ全 てメモリに乗るサイズ – ページイン・ページアウトも発生せず、実装もして いない ● ページングについては「仮想メモリ」の観点で 使用している
  • 263. 2016/04/08 荒川 祐真 263 「変換表」について ● 実際には「ページディレクトリ(PD)」と 「ページテーブル(PT)」の2種類 ページテーブルページディレクトリ 表の各行は 「エントリ」 と呼ばれる ページディレクトリエントリ (PDE) ページテーブルエントリ (PTE)
  • 264. 2016/04/08 荒川 祐真 264 「変換表」について ● 実際には「ページディレクトリ(PD)」と 「ページテーブル(PT)」の2種類 ページテーブルページディレクトリ ページディレクトリエントリは、 ページテーブルの先頭アドレスを指す
  • 265. 2016/04/08 荒川 祐真 265 「変換表」について ページテーブルページディレクトリ ページ 4KB 4KB 4KB 4KB PTEが ページの先頭アドレスを指す
  • 266. 2016/04/08 荒川 祐真 266 「変換表」について ページテーブルページディレクトリ ページ 4KB 4KB 4KB 4KB CR3 CPUのCR3というレジスタに PDの先頭アドレスが格納されている ※ 別名:PDBR(Page Directory Base Register)
  • 267. 2016/04/08 荒川 祐真 267 「変換表」について ページテーブルページディレクトリ ページ 4KB 4KB 4KB 4KB CR3 VA→PAのアドレス変換は 階層構造
  • 268. 2016/04/08 荒川 祐真 268 VAはオフセットの塊 ● PD・PT・ページ内のオフセットは どこで指定するのか?
  • 269. 2016/04/08 荒川 祐真 269 VAはオフセットの塊 ● PD・PT・ページ内のオフセットは どこで指定するのか? 全てVAに含まれている
  • 270. 2016/04/08 荒川 祐真 270 【補足】TLB ● PD・PTはメモリ上にあるため、 1度のメモリアクセスにつき、 PD・PTへのアクセスのために余分にメモリへ アクセスしなければならない ● アドレス変換高速化のため、 PDEとPTEをキャッシュするものとして TLB(トランスレーションルックアサイドバッファ)が 存在する ページングでは、アドレス変換にかかる時間がボトルネック
  • 271. 2016/04/08 荒川 祐真 271 コード行数の推移 OS5の各機能は、以下のように実装されてきた 2015/04/05 2015/08/24 2015/10/31 2015/11/30 2016/02/08システムコールの他、 特権管理、省電力機能、 ロック機能 追加 日付(ブログ記事投稿) 総 コード 行数
  • 272. 2016/04/08 荒川 祐真 272 OS5カーネルのアーキテクチャ カーネル 時間 管理 ファイルシステム システムコール デバイスドライバ アプリ shell uptime コンソール CPU メモリ KBC CRTCPIT :機能の呼び出し関係 タスク管理 スケジューラ タスクローダ メモリ管理 ページング メモリアロケータ ソ フ ト ハ ー ド 【ロック機能】 アプリケーションから 呼び出されるものではないが、 カーネルの基本機能の一つ
  • 273. 2016/04/08 荒川 祐真 273 ロック機能 ● 役割 – 「ここだけは割り込んで欲しくない」・「他のタス クへ遷移して欲しくない」という区間でロックする ● やっていること – CPUのEFLAGSレジスタのIF(割り込みイネーブル フラグ)
  • 274. 2016/04/08 荒川 祐真 274 ロック機能: 入れ子の場合の問題点 ● 入れ子にするとロックしたい区間にも関わら ず、ロックが解除されてしまう
  • 275. 2016/04/08 荒川 祐真 275 ロック機能: 入れ子問題の対処 ● 実際には「単にレジスタの制御をするだけ」で はなく、ロック状態の退避・復帰を行っている
  • 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. 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. 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. 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. 2016/04/08 荒川 祐真 280 システムコール: exec ● システムコールexecはタスク管理の機能 ● 引数でstruct fileのポインタを受け取る ● 内部的には単にタスク管理のtask_init関数を呼 び出すだけ – task_init関数はstruct fileのポインタを引数とする
  • 281. 2016/04/08 荒川 祐真 281 失敗談: ltr命令でリブート ● 現象 – ltr命令によりタスクレジスタへロードさせる と、QEMU上でリブートしてしまう ● 原因/解決方法 – GDTの4つ目にTSSのディスクリプタを配置してい たが、lgdtでGDTの範囲がディスクリプタ3つ分の ままだった
  • 282. 2016/04/08 荒川 祐真 282 失敗談: コンテキストスイッチの ljmp実行でリブートを繰り返す ● 現象 – コンテキストスイッチのljmp実行でリブートを繰り 返す ● 原因/解決方法 – shellのTSSのCR3が初期化されていなかったことが 問題であった
  • 283. 2016/04/08 荒川 祐真 283 失敗談: キー入力時、ゴミが入る ● 現象 – キー入力時、ゴミが入る ● 原因/解決方法 – デキューとエラーステータス確認の間に、キーボー ド割り込みからのエンキューが入り、エラーステー タスが上書きされてしまっていたことが原因であっ た
  • 284. 2016/04/08 荒川 祐真 284 失敗談: 作成したPTEを使用すると ブート・リブートを繰り返す ● 現象 – 作成したPTEを使用するとブート・リブートを繰り 返す – uptimeを無効化(タイマ割り込み無効化)で発生しな くなる ● 原因/解決方法 – PD初期化を間違っていた
  • 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. 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の領 域を壊した時リブート