Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
xv6 chapter5 first
Search
Tomoya Ishizaki
May 20, 2019
Programming
280
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
xv6 chapter5 first
Tomoya Ishizaki
May 20, 2019
More Decks by Tomoya Ishizaki
See All by Tomoya Ishizaki
Chompyらくとく便のこれまでとこれから
zaq1tomo
0
2.3k
【輪講】Ray: A Distributed Framework for Emerging AI Applications
zaq1tomo
2
310
xv6 chapter1 first
zaq1tomo
1
170
Hybrid Casper FFG
zaq1tomo
3
710
Other Decks in Programming
See All in Programming
Omarchy Tokyo やると聞いて UMPC 買ってセットアップしてきた
mtsmfm
0
130
{ Android | Kotlin } Gradle Plugin in 2026
ryunen344
1
300
typoなんかねぇよ
raspython3
0
680
市販E-Readerを乗っ取れ 〜Embedded Swiftで電子ペーパーガジェットを制御する〜
trickart
0
160
週末にAI-DLCを本気で回したら$1,600溶けた
hbashimizu
0
130
Swift愛好会と私(ウホーイ) / Swift Fan Club and Uhooi
uhooi
0
150
AIエージェント時代のコードレビューを設計する
nogu66
6
2.6k
AIは賢い。でも実行環境は? CLIおじさんがAI時代に伝えたいこと ~ CLIおじさんがAI時代に伝えたいこと ~
curekoshimizu
1
230
PHPプロジェクトの結合バランスを可視化する #php_night
kajitack
0
230
Webの地図
yosuke_furukawa
PRO
6
4k
AIとGame Jamで、ゲームを完成させた話
takahirosaeki
0
120
20260914 AIエージェント時代のPlatform Engineering LLM基盤とプロダクトの責務境界線
kanfab1
2
110
Featured
See All Featured
Effective software design: The role of men in debugging patriarchy in IT @ Voxxed Days AMS
baasie
0
510
JAMstack: Web Apps at Ludicrous Speed - All Things Open 2022
reverentgeek
1
590
The browser strikes back
jonoalderson
0
1.7k
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
560
Product Roadmaps are Hard
iamctodd
55
13k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.5k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4.6k
jQuery: Nuts, Bolts and Bling
dougneiner
66
8.6k
Impact Scores and Hybrid Strategies: The future of link building
tamaranovitovic
0
440
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
520
Java REST API Framework Comparison - PWX 2021
mraible
34
9.7k
How STYLIGHT went responsive
nonsquared
100
6.3k
Transcript
xv6 chapter5 first Tomoya Ishizaki
はじめに • OSは複数のプロセスを一つの物理的なCPUに 多重化している • 多重化によって各プロセスがそれぞれ固有の 仮想的なCPUを持つように動作可能 • xv6がどのように多重化を実現しているか見ていく
今日の内容 スケジューリング(前半) • 多重化 • コンテキストスイッチ • スケジューリング
今日のコード • コード:コンテキストスイッチ ◦ struct context ◦ void swtch(struct context
**old, struct context *new) • コード:スケジューリング ◦ void trap(struct trapframe *tf) ◦ void yield(void) ◦ void sched(void) ◦ void scheduler(void) • コード:mycpu & myproc ◦ struct cpu ◦ struct cpu* mycpu(void) ◦ struct proc* myproc(void)
今日の内容 スケジューリング(前半) • 多重化 • コンテキストスイッチ • スケジューリング
多重化
多重化とは • 一つの物理的な資源を複数に分割して使用し, 実際よりも多く見せること • 時間分割による多重化 ◦ CPUなど • 空間分割による多重化
◦ メモリなど
xv6はどのように多重化を実現しているか • 各CPUを時間分割し, プロセスを切り替える • xv6では2つのタイミングでプロセスを切り替え ◦ デバイスやパイプのI/Oなど(自分自身で待機) ▪ 詳しくは後半
◦ タイマー割り込みなど(強制的に切り替え) ▪ これから見ていく
多重化の実現には, いくつか課題が存在する 1. どうやって切り替えるか 2. どうやって透明的に行うか 3. どうやって競合を防ぐか 4. どうやって資源を解放するか
OSには, プロセス間調整の手段が必要 • 詳しくは後半 ◦ 親プロセスが子プロセスの終了を待つ ◦ パイプを読むとき, 書き込み完了を待つ ◦
デバイスI/O待ちなどCPUを使用していないとき, スリープして他プロセスを起こす
今日の内容 スケジューリング(前半) • 多重化 • コンテキストスイッチ • スケジューリング
コンテキストスイッチ
コンテキストスイッチとは • プロセスのコンテキストを切り替える • コンテキスト ◦ スタック ◦ レジスタ ◦
など
どうやってコンテキストスイッチを行うか • 低レイヤでは, 二種類の スイッチを行っている • 各CPUは, 固有の隔離された スケジューラスレッドをもつ •
ユーザープロセスが 他のユーザープロセスに 直接スイッチすることはない ユーザープロセスからスケジューラへ スケジューラからユーザープロセスへ
どうやってスレッドを切り替えるか • context ◦ xv6では5つのレジスタセットを保存する • 保存と復元 ◦ 現在のスレッドのcontextを保存 ◦
以前保存したスレッドのcontextを復元
今日のコード • コード:コンテキストスイッチ ◦ struct context ◦ void swtch(struct context
**old, struct context *new) • コード:スケジューリング ◦ void trap(struct trapframe *tf) ◦ void yield(void) ◦ void sched(void) ◦ void scheduler(void) • コード:mycpu & myproc ◦ struct cpu ◦ struct cpu* mycpu(void) ◦ struct proc* myproc(void)
コード:コンテキストスイッチ
struct context • コンテキストスイッチのために 5つのレジスタセットを保存する https://github.com/mit-pdos/xv6-public/blob/master/proc.h#L27
struct context • 汎用レジスタの一部を保持する ◦ %edi, %esi, %ebx, %ebp •
%eipも保持する ◦ swtch()で明示的に操作している わけではないが, allocproc()内で 保存している ◦ 詳しくは1章 https://github.com/mit-pdos/xv6-public/blob/master/proc.h#L27
void swtch(struct context **old, struct context *new) • contextを使ってレジスタを切り替える •
contextの保存と復元 ◦ old(古いcontext)を保存 ◦ new(新しいcontext)を復元 • アセンブラで実装されている https://github.com/mit-pdos/xv6-public/blob/master/swtch.S
void swtch(struct context **old, struct context *new) • **old, *new(引数)とswtchのリターンアドレス(戻り先)が
カーネルスタックに積んである • *newは移り先のプロセスのカーネルスタックを指している https://github.com/mit-pdos/xv6-public/blob/master/swtch.S ... %eip(戻り先) %ebp %ebx %esi %edi ... ... *new **old %eip(戻り先) *new oldのカーネルスタック newのカーネルスタック %esp
void swtch(struct context **old, struct context *new) • %eax が
**old を指すようになる • %edx が *new を指すようになる https://github.com/mit-pdos/xv6-public/blob/master/swtch.S ... %eip(戻り先) %ebp %ebx %esi %edi ... ... *new **old %eip(戻り先) %edx oldのカーネルスタック newのカーネルスタック %eax %edx %esp
void swtch(struct context **old, struct context *new) • 現在のレジスタをスタックに保存する https://github.com/mit-pdos/xv6-public/blob/master/swtch.S
... %eip(戻り先) %ebp %ebx %esi %edi ... ... *new **old %eip(戻り先) %ebp %ebx %esi %edi %edx oldのカーネルスタック newのカーネルスタック %eax %edx %esp
void swtch(struct context **old, struct context *new) • *old(%eaxの指すところ)が %esp
を指すようになる https://github.com/mit-pdos/xv6-public/blob/master/swtch.S ... %eip(戻り先) %ebp %ebx %esi %edi ... ... *new **old %eip(戻り先) %ebp %ebx %esi %edi %edx oldのカーネルスタック newのカーネルスタック %esp %edx *old %eax
void swtch(struct context **old, struct context *new) • %esp が
%edx を指すようになる(スタックが切り替わる) https://github.com/mit-pdos/xv6-public/blob/master/swtch.S ... %eip(戻り先) %ebp %ebx %esi %edi ... ... *new **old %eip(戻り先) %ebp %ebx %esi %edi %edx oldのカーネルスタック newのカーネルスタック *old %edx %esp %eax
void swtch(struct context **old, struct context *new) • スタックから保存したレジスタを取り出して復元する https://github.com/mit-pdos/xv6-public/blob/master/swtch.S
... %eip(戻り先) ... ... *new **old %eip(戻り先) %ebp %ebx %esi %edi %edx oldのカーネルスタック newのカーネルスタック %eax %edx %esp
void swtch(struct context **old, struct context *new) • リターンアドレス(関数の戻り先)にJMPして終了 https://github.com/mit-pdos/xv6-public/blob/master/swtch.S
... %eip(戻り先) ... ... *new **old %eip(戻り先) %ebp %ebx %esi %edi %edx oldのカーネルスタック newのカーネルスタック %eax %edx %esp
今日の内容 スケジューリング(前半) • 多重化 • コンテキストスイッチ • スケジューリング
スケジューリング
プロセスを切り替える一連の流れを見ていく • ユーザープロセスからスケジューラにスイッチ • スケジューラから別のユーザープロセスにスイッチ ※ sched関数がスケジューラへの入り口となる
スケジューラを呼ぶまでの一連の流れ • ptable.lockを獲得する • proc->stateを更新する • sched関数を呼び出す
今日のコード • コード:コンテキストスイッチ ◦ struct context ◦ void swtch(struct context
**old, struct context *new) • コード:スケジューリング ◦ void trap(struct trapframe *tf) ◦ void yield(void) ◦ void sched(void) ◦ void scheduler(void) • コード:mycpu & myproc ◦ struct cpu ◦ struct cpu* mycpu(void) ◦ struct proc* myproc(void)
コード:スケジューリング
void trap(struct trapframe *tf) https://github.com/mit-pdos/xv6-public/blob/master/trap.c#L105 • プロセスが実行中かつタイマー割り込みが発生した場合, yield関数を呼び出す • 詳しくは3章
void yield(void) • ptable.lockを獲得する • proc->stateを更新する ◦ RUNNINGから ◦ RUNNABLEに
• sched関数を呼び出す • ptable.lockを解放する https://github.com/mit-pdos/xv6-public/blob/master/proc.c#L385
void sched(void) • スケジューラへの入り口 • エラーチェックを行ってから スケジューラへスイッチする https://github.com/mit-pdos/xv6-public/blob/master/proc.c#L365
void sched(void) • エラーチェックを行い, 不正な 状態だった場合, panic()を呼ぶ ◦ ptable.lockを獲得している ◦
ロックされている ◦ プロセスが実行中である ◦ 割り込みを無効化している • 詳しくは4章 https://github.com/mit-pdos/xv6-public/blob/master/proc.c#L365
void sched(void) • 現在のCPUのintenaを保存する ◦ pushcliの前に割り込みが 有効だったかを表すフラグ ◦ 詳しくは4章 •
intenaはカーネルスレッド固有 • スレッドが切り替わる際には保存し, 復帰した際に引き継ぐ必要がある https://github.com/mit-pdos/xv6-public/blob/master/proc.c#L365
void sched(void) • swtchを呼ぶ ◦ **old ▪ プロセスのcontext ◦ *new
▪ CPUのスケジューラ https://github.com/mit-pdos/xv6-public/blob/master/proc.c#L365
void scheduler(void) • CPUごとに実行され続ける スケジューラプロセス • 以下のループを繰り返す ◦ 実行するプロセスを選択 ◦
コンテキストスイッチ ◦ 再びスケジューラに https://github.com/mit-pdos/xv6-public/blob/master/proc.c#L32
void scheduler(void) • 割り込みを有効にする ◦ 実行するプロセスが存在 しなかったときのため ◦ アイドリング •
ptable.lockを獲得する • 何らかの処理 • ptable.lockを解放する https://github.com/mit-pdos/xv6-public/blob/master/proc.c#L32
void scheduler(void) • 実行可能なプロセスが見つかる まで順番に探索する • ラウンドロビン https://github.com/mit-pdos/xv6-public/blob/master/proc.c#L32
void scheduler(void) • CPUのプロセスに選択した プロセスを設定する • switchuvm()でプロセスの ページテーブルに切り替える ◦ 詳しくは2章
• プロセスを実行中にする https://github.com/mit-pdos/xv6-public/blob/master/proc.c#L32
void scheduler(void) • swtchを呼ぶ ◦ **old ▪ CPUのスケジューラ ◦ *new
▪ プロセスのcontext https://github.com/mit-pdos/xv6-public/blob/master/proc.c#L32
void scheduler(void) • ページテーブルを切り替える ◦ 詳しくは2章 • CPUのプロセスを初期化する https://github.com/mit-pdos/xv6-public/blob/master/proc.c#L32
なぜptable.lockが必要なのか • xv6におけるinvariantの例 ◦ プロセス実行中にタイマー割り込みが発生した場合 , 別のプロセスにスイッチ可能 ▪ CPUのレジスタがプロセスの contextを保持している
▪ %cr3がプロセスのページテーブルを指している ▪ %espがプロセスのカーネルスタックを指している ◦ あるプロセスが実行可能のとき , スケジューラはそのプロセスを実行可能 ▪ プロセスのcontextがカーネルスレッドの値を保持している ▪ どのCPUもプロセスのカーネルスタック上で実行されていない ▪ どのCPUの%cr3もプロセスのページテーブルを指していない ▪ どのCPUのcpu->procもそのプロセスのことを指していない • invariantを保つために, ptable.lockの獲得が必要
コード:mycpu & myproc
struct cpu • それぞれのCPUの状態を管理する ◦ Local APIC(プロセッサ固有のID) ◦ スケジューラ ◦
など https://github.com/mit-pdos/xv6-public/blob/master/proc.h#L2
struct cpu* mycpu(void) • プロセスが実行されている CPUを返す • 割り込みを無効化してから 呼ばなくてはならない ◦
関数実行中(for等)に 割り込みが発生 ◦ 違うCPUで実行される 可能性がある https://github.com/mit-pdos/xv6-public/blob/master/proc.c#L37
struct cpu* mycpu(void) • 割り込みが無効化されて いることを確認する ◦ // Interrupt Enable
#define FL_IF 0x200 • 無効化されていなかったら panic()を呼ぶ https://github.com/mit-pdos/xv6-public/blob/master/proc.c#L37
struct cpu* mycpu(void) • Local APICを取り出す ◦ 詳しくは3章 https://github.com/mit-pdos/xv6-public/blob/master/proc.c#L37
https://github.com/mit-pdos/xv6-public/blob/master/proc.c#L37 struct cpu* mycpu(void) • CPUはグローバルな配列 cpus[]で管理 • Local APICが一致する
CPUが見つかったら返す • 見つからなかった場合 panic()を呼ぶ
struct proc* myproc(void) • 現在のCPUを取得し, 実行中のプロセスを返す • 割り込みを無効化し, 実行が 完了したら元に戻す
◦ 実行途中でプロセスが 切り替わる可能性 がある https://github.com/mit-pdos/xv6-public/blob/master/proc.c#L57
ご清聴ありがとうございました