xv6のコンテキストスイッチを読む
-
Upload
mfumi -
Category
Technology
-
view
1.665 -
download
2
description
Transcript of xv6のコンテキストスイッチを読む
![Page 1: xv6のコンテキストスイッチを読む](https://reader033.fdocument.pub/reader033/viewer/2022060111/5562fa90d8b42a4b1d8b4575/html5/thumbnails/1.jpg)
xv6のコンテキストスイッチを読む
@mfumi2
![Page 2: xv6のコンテキストスイッチを読む](https://reader033.fdocument.pub/reader033/viewer/2022060111/5562fa90d8b42a4b1d8b4575/html5/thumbnails/2.jpg)
自己紹介
● セキュリティキャンプ2012OS組
![Page 3: xv6のコンテキストスイッチを読む](https://reader033.fdocument.pub/reader033/viewer/2022060111/5562fa90d8b42a4b1d8b4575/html5/thumbnails/3.jpg)
最近こんな本が出ました
はじめてのOSコードリーディング青柳隆宏著
おすすめ! でも...
![Page 4: xv6のコンテキストスイッチを読む](https://reader033.fdocument.pub/reader033/viewer/2022060111/5562fa90d8b42a4b1d8b4575/html5/thumbnails/4.jpg)
UNIX V6 を読む上で大変なところ
● PDP11● Cの記法が古い (pre K&R)● アセンブラの記法が特殊● デフォルトが8進数● etc...
![Page 5: xv6のコンテキストスイッチを読む](https://reader033.fdocument.pub/reader033/viewer/2022060111/5562fa90d8b42a4b1d8b4575/html5/thumbnails/5.jpg)
xv6とは
● MITで開発された教育用OS http://pdos.csail.mit.edu/6.828/2012/xv6.html
● UNIX V6 を x86 向けに書き直したもの● 解説書有り
http://pdos.csail.mit.edu/6.828/2012/xv6/book-rev7.pdf
![Page 6: xv6のコンテキストスイッチを読む](https://reader033.fdocument.pub/reader033/viewer/2022060111/5562fa90d8b42a4b1d8b4575/html5/thumbnails/6.jpg)
xv6の特徴
● x86● マルチプロセッサ対応● バイナリはELF● スワッピング機能はなし● qemu+gdb で動作可
![Page 7: xv6のコンテキストスイッチを読む](https://reader033.fdocument.pub/reader033/viewer/2022060111/5562fa90d8b42a4b1d8b4575/html5/thumbnails/7.jpg)
コンテキストスイッチ
● プロセスのコンテキストを切り替える● コンテキスト …
– メモリ空間→ cr3 レジスタを切り替える
– スタック→ %esp を切り替える
– 各種レジスタ→ プロセスごとのスタックに退避&スタックから復帰
![Page 8: xv6のコンテキストスイッチを読む](https://reader033.fdocument.pub/reader033/viewer/2022060111/5562fa90d8b42a4b1d8b4575/html5/thumbnails/8.jpg)
xv6のコンテキストスイッチ• switch.S
void swtch(struct context **old, struct context *new);
• proc.h
![Page 9: xv6のコンテキストスイッチを読む](https://reader033.fdocument.pub/reader033/viewer/2022060111/5562fa90d8b42a4b1d8b4575/html5/thumbnails/9.jpg)
xv6のコンテキストスイッチ• switch.S
void swtch(struct context **old, struct context *new);
%edi%esi%ebx%ebp%eip(swtchの戻り先)
メモリ%%%%%eip(swtchの戻り先)
%esp★
new(%edx)
![Page 10: xv6のコンテキストスイッチを読む](https://reader033.fdocument.pub/reader033/viewer/2022060111/5562fa90d8b42a4b1d8b4575/html5/thumbnails/10.jpg)
xv6のコンテキストスイッチ• switch.S
void swtch(struct context **old, struct context *new);
%edi%esi%ebx%ebp%eip(swtchの戻り先)
%edi%esi%ebx%ebp%eip(swtchの戻り先)
%esp
メモリ
★
new(%edx)
![Page 11: xv6のコンテキストスイッチを読む](https://reader033.fdocument.pub/reader033/viewer/2022060111/5562fa90d8b42a4b1d8b4575/html5/thumbnails/11.jpg)
xv6のコンテキストスイッチ• switch.S
void swtch(struct context **old, struct context *new);
%edi%esi%ebx%ebp%eip(swtchの戻り先)
%edi%esi%ebx%ebp%eip(swtchの戻り先)
%esp
メモリ
★
new(%edx)
![Page 12: xv6のコンテキストスイッチを読む](https://reader033.fdocument.pub/reader033/viewer/2022060111/5562fa90d8b42a4b1d8b4575/html5/thumbnails/12.jpg)
xv6のコンテキストスイッチ• switch.S
void swtch(struct context **old, struct context *new);
%edi%esi%ebx%ebp%eip(swtchの戻り先)
%edi%esi%ebx%ebp%eip(swtchの戻り先)
%espメモリ
★
new(%edx)
![Page 13: xv6のコンテキストスイッチを読む](https://reader033.fdocument.pub/reader033/viewer/2022060111/5562fa90d8b42a4b1d8b4575/html5/thumbnails/13.jpg)
xv6のコンテキストスイッチ• switch.S
void swtch(struct context **old, struct context *new);
%edi%esi%ebx%ebp%eip(swtchの戻り先)
%edi%esi%ebx%ebp%eip(swtchの戻り先)
%espメモリ
★
new(%edx)
![Page 14: xv6のコンテキストスイッチを読む](https://reader033.fdocument.pub/reader033/viewer/2022060111/5562fa90d8b42a4b1d8b4575/html5/thumbnails/14.jpg)
xv6のコンテキストスイッチ• switch.S
void swtch(struct context **old, struct context *new);
%edi%esi%ebx%ebp%eip(swtchの戻り先)
%edi%esi%ebx%ebp%eip(swtchの戻り先)
%esp
*old(%eax)
メモリ
★ new(%edx)
![Page 15: xv6のコンテキストスイッチを読む](https://reader033.fdocument.pub/reader033/viewer/2022060111/5562fa90d8b42a4b1d8b4575/html5/thumbnails/15.jpg)
xv6のコンテキストスイッチ• switch.S
void swtch(struct context **old, struct context *new);
%edi%esi%ebx%ebp%eip(swtchの戻り先)
%edi%esi%ebx%ebp%eip(swtchの戻り先)
%esp
メモリ
★
*old(%eax)
new(%edx)
![Page 16: xv6のコンテキストスイッチを読む](https://reader033.fdocument.pub/reader033/viewer/2022060111/5562fa90d8b42a4b1d8b4575/html5/thumbnails/16.jpg)
xv6のコンテキストスイッチ• switch.S
void swtch(struct context **old, struct context *new);
%edi%esi%ebx%ebp%eip(swtchの戻り先)
%edi%esi%ebx%ebp%eip(swtchの戻り先)
%esp
メモリ
★
new(%edx)
*old(%eax)
![Page 17: xv6のコンテキストスイッチを読む](https://reader033.fdocument.pub/reader033/viewer/2022060111/5562fa90d8b42a4b1d8b4575/html5/thumbnails/17.jpg)
xv6のコンテキストスイッチ• switch.S
void swtch(struct context **old, struct context *new);
%edi%esi%ebx%ebp%eip(swtchの戻り先)
%edi%esi%ebx%ebp%eip(swtchの戻り先)
%esp
メモリ
★
new(%edx)
*old(%eax)
![Page 18: xv6のコンテキストスイッチを読む](https://reader033.fdocument.pub/reader033/viewer/2022060111/5562fa90d8b42a4b1d8b4575/html5/thumbnails/18.jpg)
xv6のコンテキストスイッチ• switch.S
void swtch(struct context **old, struct context *new);
%edi%esi%ebx%ebp%eip(swtchの戻り先)
%edi%esi%ebx%ebp%eip(swtchの戻り先)
%esp
メモリ
★
new(%edx)
*old(%eax)
![Page 19: xv6のコンテキストスイッチを読む](https://reader033.fdocument.pub/reader033/viewer/2022060111/5562fa90d8b42a4b1d8b4575/html5/thumbnails/19.jpg)
xv6のコンテキストスイッチ• switch.S
void swtch(struct context **old, struct context *new);
%edi%esi%ebx%ebp%eip(swtchの戻り先)
%edi%esi%ebx%ebp%eip(swtchの戻り先)
%esp
メモリ
★
new(%edx)
*old(%eax)
![Page 20: xv6のコンテキストスイッチを読む](https://reader033.fdocument.pub/reader033/viewer/2022060111/5562fa90d8b42a4b1d8b4575/html5/thumbnails/20.jpg)
xv6のコンテキストスイッチの流れ
ユーザプロセス1 ユーザプロセス2 タイマ割り込み iret
割り込みハンドラ スケジューラ 割り込みハンドラ swtch() swtch()
![Page 21: xv6のコンテキストスイッチを読む](https://reader033.fdocument.pub/reader033/viewer/2022060111/5562fa90d8b42a4b1d8b4575/html5/thumbnails/21.jpg)
(1) 割り込みの発生
● xv6では100msごとにタイマ割り込みが発生● 割り込みが発生すると
– 特権レベルが3から0に移行– スタックがカーネルスタックに切り替わる
(TSSからカーネル用%espと%ssを読み込む)– スタックに%ss, %esp, %eflags, %cs, %eip を積む
(現在実行していたプロセスの状態を積む)– 対応する割り込みハンドラに移行
![Page 22: xv6のコンテキストスイッチを読む](https://reader033.fdocument.pub/reader033/viewer/2022060111/5562fa90d8b42a4b1d8b4575/html5/thumbnails/22.jpg)
(1) 割り込みの発生
xv6では● vectors.S (vectors.plから生成される) 内に定義してあ
る vector$i() ($iは割り込み番号) が呼び出される(割り込みハンドラの設定は trap.c の tvinit(), idtinit(), いずれも main.cのmain()から呼ばれる )
● vector$i から trapasm.S の alltraps() に飛ぶ
![Page 23: xv6のコンテキストスイッチを読む](https://reader033.fdocument.pub/reader033/viewer/2022060111/5562fa90d8b42a4b1d8b4575/html5/thumbnails/23.jpg)
(2) 割り込みハンドラの処理● trapasm.S alltraps
・自動に退避されないレジスタを退避・カーネル用セグメントの設定・最終的に trap.c の trap()を呼ぶ
![Page 24: xv6のコンテキストスイッチを読む](https://reader033.fdocument.pub/reader033/viewer/2022060111/5562fa90d8b42a4b1d8b4575/html5/thumbnails/24.jpg)
(2) 割り込みハンドラの処理
● trap.c の trap() でそれぞれの処理に応じた割り込み処理をおこなう(割り込みハンドラごとに処理をおこなっていない)
● タイマ割り込みの場合 CPU 時間切れなら proc.c の yield()を呼ぶ● yield()からさらに proc.cの shced()が呼ばれる
タイマ割り込み → vectors.S#vector$i() → trapasm.S#alltraps() → trap.c#trap() → proc.c#yield() → proc.c#shced()
![Page 25: xv6のコンテキストスイッチを読む](https://reader033.fdocument.pub/reader033/viewer/2022060111/5562fa90d8b42a4b1d8b4575/html5/thumbnails/25.jpg)
(2) 割り込みハンドラの処理● proc.c の sched()
スケジューラプロセスにコンテキストスイッチする
・proc‥現在のプロセスの情報をもつ構造体・cpu‥各CPUが持つCPUの情報をもつ構造体それぞれproc.h で定義
コンテキストの切り替え•swtch()からの戻り先 (cpu->scheduler.eip) は proc.c の scheduler()
![Page 26: xv6のコンテキストスイッチを読む](https://reader033.fdocument.pub/reader033/viewer/2022060111/5562fa90d8b42a4b1d8b4575/html5/thumbnails/26.jpg)
(3) スケジューラの処理
★ sched()のswtch()からの戻り先メモリ空間をカーネル用に切り替え
次に実行するプロセスを探す(ラウンドロビン)
メモリ空間の切り替え選択したプロセスにswtch()
proc.c scheduler()
![Page 27: xv6のコンテキストスイッチを読む](https://reader033.fdocument.pub/reader033/viewer/2022060111/5562fa90d8b42a4b1d8b4575/html5/thumbnails/27.jpg)
(3) スケジューラの処理
● 何故sched()のswtch()からscheduler()に戻るのか?→ ブートローダから呼ばれることになる main.c の main()でinitプロセス(proc[0])を起動後shceduler()を呼ぶため
![Page 28: xv6のコンテキストスイッチを読む](https://reader033.fdocument.pub/reader033/viewer/2022060111/5562fa90d8b42a4b1d8b4575/html5/thumbnails/28.jpg)
(4) 割り込みハンドラの処理(後半)● proc.c の sched()
scheduler() から swtch() によって選択されたプロセスの再開
ここから処理が再開★
![Page 29: xv6のコンテキストスイッチを読む](https://reader033.fdocument.pub/reader033/viewer/2022060111/5562fa90d8b42a4b1d8b4575/html5/thumbnails/29.jpg)
(4) 割り込みハンドラの処理(後半)
● 最終的にalltrap() まで return し,そこで iret して割り込み終了● iret でスタックからプロセスの状態を復帰させる.このとき特権レ
ベルも3に戻るスタックが切り替わっているので別のプロセス状態に戻る
trapasm.S
%eip%cs%eflags%esp%ss
メモリ
![Page 30: xv6のコンテキストスイッチを読む](https://reader033.fdocument.pub/reader033/viewer/2022060111/5562fa90d8b42a4b1d8b4575/html5/thumbnails/30.jpg)
xv6のコンテキストスイッチの流れ(再掲)
ユーザプロセス1 ユーザプロセス2 タイマ割り込み iret
割り込みハンドラ スケジューラ 割り込みハンドラ swtch() swtch()
![Page 31: xv6のコンテキストスイッチを読む](https://reader033.fdocument.pub/reader033/viewer/2022060111/5562fa90d8b42a4b1d8b4575/html5/thumbnails/31.jpg)
まとめ
● PDP11がいやな人はxv6読んでみたらどうでしょうか● いろいろと改造のしどころ有り