オペレーティングシステム
加藤 真平
東京大学 大学院情報理工学系研究科
[email protected]
PFLab(加藤研)のウェブサイトからダウンロードできます。 ⇒http://www.pf.is.s.u-tokyo.ac.jp/ja/classes/講義概要
• 受講生に求める基礎知識
– C言語の理解
– コンピュータアーキテクチャの基礎の理解
• メモリ管理、割り込み、CPUモード
• 参考図書
– Silberschatz, Galvin, and Gagne, Operating System
Concepts 8th Edition,
Wiley
• 成績
講義スケジュール(予定)
1. OSの概要(4/8) 2. プロセス管理(4/15) 3. プロセス間交信、スレッド(4/22) 4. プロセス同期(5/13) 5. CPUスケジューリング 1(5/20)6. CPUスケジューリング 2 & トランザクション処理&メモリ管理1(5/27) 7. メモリ管理2(6/3) 8. 休講予定(6/10) 9. メモリ管理&I/Oシステム(6/17) 10. I/Oシステム(6/24) 11. ファイルシステム(7/1) 12. プロテクション&セキュリティ (7/8) 13. バッチシステム&分散システム&まとめ(7/22) 14. 試験(7/29)
システムコール(プリミティブ)
• システムコールはユーザプログラムとOSとのインター
フェイス
– 割り込み命令によって実現
– C,C++などのプログラミング言語向けインターフェイスを提供
– Unix系ではマニュアル2章がシステムコール、3章が言語ライ
ブラリ
• 2章のopen/read/write/closeはシステムコール • 3章のfopen/fread/fwrite/fcloseはシステムコールを使用し、ライブラリレ ベルでバッファを処理システムコールの仕組み
(1) システムコール関数の呼出し (2) ライブラリ関数内で、 trap命令を発行 - レジスタにシステムコール番号 (3) カーネルモードに移行 割込みハンドラを起動 (4) システムコール引数を検査しカーネル 内へコピー (5) システムコール番号と関数ポインタの 表から呼び出しルーチンを特定 処理ルーチンの実行 (6) システムコール処理結果をユーザ 空間へコピー (7) 適切なプロセスのスケジュール システムコール処理ルーチン #1 システムコール処理ルーチン #2 システムコール処理ルーチン #k システムコール処理ルーチン #n ... システムコール表 ディスパッチャ (3) 割込みハンドラ (1) システムコール関数の呼出し(#k) (2) trap命令の発行 ユーザプログラム カーネルモード ユーザモード (4) 引数のコピー (5) システムコール処理の実行 (6) 返戻値のコピー (7) プロセスのスケジュール システムコール ライブラリ関数プロセス管理
• プロセスとは?
– プログラムの実行単位
– 次のような資源を使用
• CPU時間 • メモリ • ファイル • I/Oデバイス• OSによるプロセス管理の例
– プロセス生成・削除
– プロセス停止・再開
ユーザ プログラムコード ユーザ データ領域 プロセス状態 格納領域 カーネル プログラムコード カーネル作業領域 ユーザ ヒープ領域 ユーザ スタック領域ユーザ空間
プロセス管理
• プロセスごとに仮想空間を割り当て
• 他のプロセスのメモリへのアクセス禁止
• バグ等でプロセスが異常終了しても、他のプロ セスには影響なし• プロセスの種類(後述)
• 権限による分類
• ユーザプロセス • スーパーユーザープロセス• 形態による分類
• システムプロセス・デーモンプロセス • サーバープロセス ユーザ プログラムコード ユーザ データ領域 プロセス状態 格納領域 カーネル プログラムコード カーネル作業領域 ユーザ ヒープ領域 ユーザ スタック領域ユーザ空間
カーネル空間
仮想記憶の仕組み
• ページサイズ 1,024バイトの場合 プロセスのページ表ポインタ オフセット 論理ページ番号 物理ページ番号 V I V 0 1 2 3 4 物理メモリ 仮想メモリ 10bits 0x0 0x0400 0x0800 0x0c00 0x1000 0x1400 1 0 2 I V I I I I I アクセスパターン 0x0200 0x0900 0x0d00 #define V 1 #define I 0 struct PTBL { int valid; int pno; }; Struct PTBL[10] = {プロセスと仮想記憶
プロセスのページ表ポインタ オフセット 論理ページ番号 物理ページ番号 V I V 0 1 2 3 4 物理メモリ 10bits 1 0 2 I V I I I I I ページ表 物理ページ番号 V I V 1 4 3 I V I I I I I ページ表 仮想メモリ 0x0 0x0400 0x0800 0x0c00 0x1000 0x1400 0x1800プロセスの種類
• 権限による分類
– ユーザプロセス
• 一般ユーザ– スーパーユーザプロセス(ルート権限を有するプロセス)
• 特権機能を使用可能 – 例:任意のユーザプロセスの停止、システム停止プロセスの種類
• 形態による分類
– システムプロセス、デーモンプロセス
• オペレーティングシステムサービスを提供しているプロセスで スーパーユーザモード(CPUの特権モードとは違う)で動いてい るプロセスの総称 • システムプロセスでユーザからは見えないところで動いているプ ロセス=デーモンプロセス– サーバプロセス
• クライアント・サーバモデルに基づいたサービスを提供している プロセス=サーバプロセス • httpデーモン、httpサーバ、httpシステムプロセスどんなプロセスが動いている?
• Linuxの場合
– topコマンド
– psコマンド
• ps axwwwl
• Windowsの場合
– Ctl+Alt+Delして、タスクマネジャーを選択
ユーザ text, data,bss 領域 カーネル領域 mmap領域 スタック カーネル領域 mmap領域 ユーザ text, data,bss 領域 スタック
x86系Linuxの仮想メモリ空間使用
カーネル領域 mmap領域 ユーザ text, data,bss 領域 スタック 0x00000000 0x40000000 0xc0000000 0xffffffff text: プログラムコード data:初期データ bss: 初期データのない領域プロセス
mmap領域 スタック loginプロセス login プログラム メモリイメージ … exec(“/bin/sh”, ….);プロセス
カーネル領域 mmap領域 スタック loginプロセス login プログラム メモリイメージ … exec(“/bin/sh”, ….); execシステム コールが実行さ れると・・・プロセス
mmap領域 スタック /bin/shプロセス sh プログラム メモリイメージ pid = fork(); if (pid == 0) { exec(cmd, …); } else { …. } メモリイメージが書 き換わり、新たなプ ロセスが実行プロセス
カーネル領域 mmap領域 スタック /bin/shプロセス sh プログラム メモリイメージ pid = fork(); if (pid == 0) { exec(cmd, …); } else { …. } forkシステムコールが 実行されると・・・プロセス
mmap領域 スタック /bin/shプロセス(親プロセス) sh プログラム メモリイメージ pid = fork(); if (pid == 0) { exec(cmd, …); } else { …. } カーネル領域 mmap領域 スタック sh プログラム pid = fork(); if (pid == 0) { exec(cmd, …); } else { …. } メモリが複製 /bin/shプロセス(子プロセス)プロセス
カーネル領域 mmap領域 スタック /bin/shプロセス(親プロセス) sh プログラム メモリイメージ pid = fork(); if (pid == 0) { exec(cmd, …); } else { …. } カーネル領域 mmap領域 スタック sh プログラム pid = fork(); if (pid == 0) { exec(cmd, …); } else { …. } 複製元(親プロセス):forkシステムコールの返り値は、子プロセスのID (identifier:識別子) 複製先(子プロセス):forkシステムコールの返り値は、0 /bin/shプロセス(子プロセス)プロセス
mmap領域 ユーザ text, data,bss 領域 スタック loginプロセス shellプロセス カーネル領域 mmap領域 ユーザ text, data,bss 領域 スタック lsプロセス execシステ ムコールに よりshellプ ログラムが 起動 forkシステ ムコールに よってプロ セスを生成 さらに、 mmap領域 ユーザ text, data,bss 領域 スタック補足
• fork()について
– オープン済みのファイル記述子は共有 – vfork() – メモリ保護によりアクセス時にコピー(copy on write) – 現在ではobsolete(既に古い) – 現在はfork()がメモリ保護を用いたcopy on writeで実現されている 共有 code data stack code data stack コピー コピー 共有 共有 code data stack code data stack コピー 古典的なfork() 特殊なfork() → スレッド(後述) fork()時のデータ 領域とスタック領 域をコピー スタック領域のみ コピー(データ領域 へのアクセスに注 意が必要)プロセス実行の切り替え
• Linux/Unixでは、コマンド実行毎にプロセス作成
• プロセス実行の切り替え=プロセスコンテキストスイッチ、
コンテキストスイッチ
ユーザ プログラムコード ユーザ データ領域 プロセス状態 格納領域 カーネル ユーザ ヒープ領域 ユーザ スタック領域 ユーザ空間 A ユーザ プログラムコード ユーザ データ領域 プロセス状態 格納領域 カーネル ユーザ ヒープ領域 ユーザ スタック領域 ユーザ空間 B コンテキストスイッ チ時にOSは何をする か?Process Control Block (PCB)とプロセス切り替え
• PCBにプロセス毎に必要な情報を格納する
– プロセスの状態 – CPUレジスタ – プライオリティ等のCPU スケジューリング情報 – ページテーブル等のメモリ管理情報etc…
プロセスコンテキストの様子補足
演算ユニット • コード(テキスト)領域 • プログラム • データ領域 • data – 初期化された静的変数 – 大域変数 • bss – 初期化されない静的変数 – 大域変数 • heap – 動的確保変数 code (text) data bss heap リターンアドレス auto変数 code (text) data bss heap リターンアドレス 引数など auto変数メモリ空間とセクション
プログラム カウンタ(PC) レジスタ フレーム ポインタ 各領域の アドレスプロセスの状態
• New
– プロセス生成中
• Running
– 実行中
• Waiting
– 何かの事象待ち
• Ready
– 実行可能.
• Terminated
– 実行終了
プロセススケジューリングキュー
• プロセススケジューリングキューの種類
– Job queue
• 全プロセスリスト– Ready queue
• 実行可能状態のプロセスリスト– Device queues
• I/O待ち状態プロセスリストプロセスの実行とキュー
head tail registers . . . registers . . . Ready queue PCB PCB‘ head tail I/O queue CPUで実行• プロセスの実行中に起こること
– プロセスがI/O要求 – 割り当てられたCPU時間(Time slice)が経過 – 子プロセスを生成 – 割り込みが発生補足
最高優先度の実行可能キュー 最低優先度の実行可能キュー null null 優 先 度 高 . . .次に実行状態
待ちイベントが発生し
たら、実行可能状態へ
実行状態スケジューラの種類
• 長期スケジューラ (job scheduler)
– バッチシステムでは、ジョブ(プロセス)が投入されると、
それらは2次記憶に配置 (spool呼ぶ)
– スプールされたジョブの中からいくつかのジョブを取り出し
て実行可能キューに投入
• 短期スケジューラ (CPU scheduler)
– どのプロセスを次に実行するか決定す
短期スケジューラ
• 短期スケジューラ
– プロセスが待ち状態になるときに、次に実行すべきプロセス
を決めるために起動
– プロセスが実行を続けている場合でも、Time Slice毎に起動
– 処理が速いことが必要条件
• 100ミリ秒毎に10ミリ秒もかかると、10/(100+10)= 9%がオーバヘッド になってしまう 普通は数十から数百マイクロ秒のオーダ長期スケジューラ
• 秒あるいは分毎に実行される
• マルチプログラミングの度合いを制御
– 同時に実行するプロセスの数を決定
– プロセス数を一定にするならば、長期スケジューラはプロセ
スが消滅したときにのみ実行
• 遅くても良い
• プロセスの性質に応じてスケジューリングする
– I/O-bound プロセス
• I/O処理 多 CPU使用 少– CPU-bound プロセス
• CPU使用 多(数値計算など)TSSにおけるスケジューラ
• TSS(Time Sharing System)は長期スケジューラなし
• 長期スケジューラの替わりに中期スケジューラがある
場合あり
– マルチプログラミングの度合いを減らすために、実行可能プ
ロセスを実行可能キューから取り出し(swap out)
プロセス生成一般論(1/2)
• プロセスはプロセスを生成することができる
– 親プロセス:生成側 ⇔ 子プロセス:作られた側
– 子プロセスはさらにその子プロセスを生成可能
• それにより、プロセスのツリー形成• 資源の共有可能性
– 親と子供は全ての資源を共有
– 子プロセスは親プロセスの一部の資源を共有
– 親子で共有する資源なし
• 実行関係
– 親と子供は同時に実行
– 親プロセスは子プロセスの終了を待つことが可能
プロセス生成一般論(2/2)
• メモリ空間
– 子プロセスは親プロセスのメモリ空間の複製を保持
– 子プロセスはプログラムを読み込み実行
• UNIX系の例
– forkシステムコール
• 子プロセスははじめ親プロセスのメモリ空間の複製を保持
– 実装上は共有&Copy on Write
• 子プロセスは親プロセスのファイルディスクリプタの複製
を保持
– execシステムコール
プロセスの終了一般論
• プロセスは最後にexitシステムコールをして、プロセスを終了
– exitシステムコール時に終了コードを渡すことが可能 – 親プロセスは、子プロセスの終了をwaitシステムコールで待機が可能 • その際、子プロセスの終了コードの取得が可能• プロセス終了時にするべきこと
– プロセスが保持している資源の解放:メモリ領域、I/Oバッファなど• 親プロセスはabortシステムコール(Unix系の場合kill)で子プロセス
を終了させることが可能
• 親プロセスが終了すると子プロセスも終了させられるシステムも
存在
– Cascading termination – Linuxの場合は? • 親プロセスが終了すると子プロセスは、initプロセスが親にUNIX におけるプロセスツリー
• カーネルの初期化が終了すると、/sbin/initプログラムを探し、プ
ロセスを起動
• initプロセスは以下の処理を実行
– /etc/rc.d/rc.sysinitスクリプトの実行
– /etc/inittabスクリプトの実行
– /etc/rc.d/rc.localスクリプトの実行
• initプロセスの下に新たなプロセスが生成
スレッド
• Thread of Control
– プロセス内での一連の実行の流れ – 単にスレッドとも• プロセス内に複数スレッドを動
かすような実行モデル
=マルチスレッドモデル
• 多くの研究がなされたのは、マ
ルチスレッドモデルは共有メモ
リ型並列コンピュータが一般に
使えるようになった1970年後半
から1980年代
補足
• スレッドのContext(管理実体)
は小さい
– 切替が高速
– 但し、共有データのア
クセスに注意が必要
• プログラムから見るとプロ
グラム中の関数が別の処理
として動作
code data stack register メモリ スレッド プロセス メモリ register スレッド プロセス register スレッド register スレッド main() func1() func2() int func1() { ... } int func2() { ... } int main() { thread_create(func1); thread_create(func2); } int func2() { ... } int func1() { func2(); } int main() { func1(); } マルチスレッド 単一スレッドスレッドの実現方法
• ユーザレベルスレッド
– ユーザライブラリで実現
• カーネルレベルスレッド
ユーザレベルスレッド
• ユーザモードで動作するライブラリで実現
– 多くの場合setjmp()/longjmp()で実装
• フレーム情報の保存と復元
• 各スレッドは別の起点フレームを保持
• カーネルレベルスレッドより軽量
– 高速のコンテクスト切り換え
– 大量のスレッド生成が可能
• スケジューリングの方針等の変更が手軽
threadB threadCユーザレベルスレッド
• スケジューリングの面倒をカーネルが見ない
– 処理を横取りできない or 横取りの実現が面倒
– 入出力等でスレッドが待ち状態になると、
同一プロセス内の他の実行可能スレッドが
実行不可能 (I/Oブロック)
• システムコールライブラリのwrapper等で対処– 実行コアが複数でも並列に実行不可能
main threadA threadB threadCカーネルレベルスレッド
• カーネル内でプロセスと同様の手法でスレッドを管理
– サイズ:スレッド制御ブロック(Thread Control Block)< PCB
• スレッドはカーネルによるスケジューリングの対象
– コンテクストスイッチ等の操作は、カーネルモードで実行
– カーネルモードとユーザモードの切り替えオーバヘッドが発生
• ただし、プロセスの切替よりは軽量
マルチスレッド実現モデル
• Many-to-One(多対1モデル)
– 複数のユーザレベルスレッドがカーネルで実現されているス
レッドひとつに対応
• One-to-One(1対1モデル)
– ひとつのユーザスレッドがカーネルで実現されているスレッド
ひとつに対応
• Many-to-Many(多対多モデル)
– 複数のユーザレベルスレッドが複数のカーネルレベルスレッド
に対応
マルチスレッドのモデル
• Many-to-One(多対1モデル)
– 一つのカーネルスレッドで 複数のユーザスレッドを稼働 – ライブラリでスケジューリング するため高速 – カーネルの処理待ちできるのは 一つのスレッドのみ • I/Oでブロック• 実装
process ユーザ レベル スレッド スケジューラマルチスレッドのモデル
• One-to-One
(1対1モデル)
– 一つのカーネルスレッドで
ただ一つのユーザスレッド
が稼働
– 他のスレッドのI/Oブロッ
クと無関係
– 複数プロセッサで稼働
– スレッド生成・管理のオー
バヘッドが発生
• 実装
– Linux, Windows k process ユーザ レベル スレッド カーネル レベル スレッド k k kマルチスレッドのモデル
• Many-to-Many(多対多モデル)
– 複数のユーザスレッドを その数以下のカーネル スレッドで稼働 – カーネルスレッドの数は アプリケーションやマシン に応じて決定 – スレッドをどう割り付けるか の制御が必要 ユーザ レベル スレッド スケジューラ processマルチスレッドのモデル
• 2レベルモデル
– 多対多モデルのバリエーション – 一部のユーザレベル スレッドを特定のカーネル スレッドに固定(pin down)• 実装
– IRIX, HP-UX, Tru64 UNIX – Solaris (before ver. 9)
k ユーザ レベル スレッド カーネル レベル スレッド k k スケジューラ process
Linux Threads
• POSIX Pthreadが提供されている
– スレッドライブラリの標準規格 (IEEE 1003.1c)
– 多くのUnix系システムで実装
• Pthread実現方法
– clone() システムコール
マルチスレッドの利点(1/2)
• 並列コンピュータ上でのプロセッサの有効利用
– 共有メモリ型並列コンピュータ上で、プロセッサを有効利用
が可能
– マルチコアを活用可能
• マルチコアの時代 – 半導体集積度が向上したが、クロックを上げられない(リーク電 流&熱問題) – 余った回路の使い道としてチップ内に複数プロセッサを搭載マルチスレッドの利点(2/2)
• 資源を共有可能
– ファイルディスクリプタやメモリ領域の共有、メモリ管理の
ための構造体の共有、TLBの共有が可能
• TLBの共有によりコンテキストスイッチ時にTLB flushが不必要• 応答性の向上
– 例えばマルチスレッドWEBブラウザでは、イメージを読み込
んでいるスレッドとユーザの入力を同時に処理が可能
• シングルスレッドの場合は、selectを使ったevent driven処理
スレッド利用の場面
• サーバプロセスの応答性の向上
– サーバプログラム
• 要求ごとにスレッドを生成し、処理と結果の応答を担当
• 例:HTTPサーバ
– それぞれ別のスレッドでリクエストを処理
– ウィンドウシステム
• それぞれ別のスレッドでイベントを待つ処理
スレッド利用の場面
• CPU処理と入出力処理の分割
– プロセスPの処理を、計算を行うスレッド(Th1)
と入出力を行うスレッド(Th2)に分割
• Th1とTh2は1つのプログラムを実行
– 入出力待ちの間,Th2は待ち状態になるがTh1の
処理は継続
Th2(入出力) 入出力待ちスレッド利用の場面
• 並列計算
– 並列計算機を使って高速計算
– 例:行列の掛け算
• 各行を別スレッドで計算
• メモリ空間を共有するので、プロセス間通信
するより高速
×
=
(補足)カーネルもマルチ化の時代
従来型のカーネル(SMP) マルチカーネル(AMP)