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

xv6のコンテキストスイッチを読む

4,186 views

Published on

第2回APASEC+第2期サイボウズ・ラボユース合同勉強会 (2013/3/29) 発表資料

Published in: Technology
  • Be the first to comment

xv6のコンテキストスイッチを読む

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

×