🎓 レベル:基礎 | 重要度:A(必須)
📎 前提:入出力とバス・割り込み | 関連:プロセスとスレッド・物理メモリと論理アドレス
要点(BLUF)
- OSの本質は 資源(CPU・メモリ・I/O)の管理者であり、各プログラムに「自分専用のマシンがあるように見せる」仮想化の層。
- CPUは 特権モード(カーネル) と ユーザモード(アプリ) の二層で動く。ハードを直接いじる危険な操作はカーネルだけに許す。
- アプリがI/Oなどを行いたいときは システムコールでカーネルに依頼する。これは「ユーザ→カーネル」へ安全に橋を架ける唯一の入口。
概念 ── OSは「ハードの受付係 兼 警備員」
コンピュータには1つのCPU(実際は数コア)、有限のメモリ、各種I/O機器しかありません。そこで多数のプログラムを同時に走らせ、互いに干渉させず、ハードを壊させないために、仲介者が要ります。それがOSです。
OSの仕事は大きく2つ:
- 仮想化(抽象化):物理資源を扱いやすい形に見せる。1つのCPUを「各プロセス専用CPU」に、物理メモリを「各プロセス専用アドレス空間」(物理メモリと論理アドレス)に、ディスクを「ファイル」(ファイルシステムの構造)に。
- 保護と調停:あるプログラムが他のメモリを壊したり、ハードを独占したりしないよう、アクセスを管理し公平に配分する(CPUスケジューリング)。
要するにOSは、限られたハードを「みんなが安全に・公平に使える共有設備」に変える管理者です。
仕組み① ── 特権モードとユーザモード
もしどのプログラムもハードを直接いじれたら、1つのバグや悪意が全体を巻き込みます。そこでCPUは2つの動作モードを持ちます。
flowchart TB
subgraph U["ユーザモード(アプリが動く・権限が低い)"]
app["アプリA / アプリB / ..."]
end
subgraph K["カーネルモード(特権・ハードを直接操作)"]
kern["カーネル(スケジューラ・メモリ管理・ドライバ)"]
end
app -->|"システムコール (trap)"| kern
kern -->|"結果を返す / 復帰"| app
- ユーザモード:アプリが動く。特権命令(I/O命令、メモリ保護設定の変更、割り込み禁止など)は実行できない。試みるとCPUが例外を上げOSが介入。
- カーネルモード:OSの中核(カーネル)だけが入れる。全ハードにアクセスできる。
この線引きがあるから、アプリのバグはそのプロセス内に閉じ、カーネルとOS全体は守られます。CPUがハード機構として「今どちらのモードか」を持つのがポイント(ソフトの約束だけでは破れる)。
仕組み② ── システムコール
ユーザモードのアプリがファイルを読む・メモリを増やす・プロセスを作るには、結局カーネルの力が要ります。その依頼の窓口が システムコールです。
sequenceDiagram
participant A as アプリ(ユーザモード)
participant C as CPU
participant K as カーネル(特権モード)
A->>C: システムコール命令 (trap)
Note over C: モードをカーネルへ切替・PCをハンドラへ
C->>K: システムコールハンドラ起動
K->>K: 引数を検証し処理(例: ディスク読み取り)
K-->>C: 復帰命令
Note over C: モードをユーザへ戻す
C-->>A: 戻り値を返す
read() や write()、open()、fork()(プロセスとスレッド)といったライブラリ関数の内部は、最終的にこのtrap命令でカーネルへ制御を移します。これは 入出力とバス・割り込み の割り込みと同じ「PCを書き換えてハンドラへ飛ぶ」機構を、ソフトから意図的に起こすもの(ソフトウェア割り込み)。
要するにシステムコールは、特権の壁に開いた、検査付きの唯一の窓口。アプリは「何をしてほしいか」だけを渡し、危険な操作の実体はカーネルが代行します。
具体例 ── 実機でシステムコールを覗く
Linuxでは strace でプロセスが発行するシステムコールを一覧できます(対応ラボ)。strace ls とすると、openat・read・write・close などが並び、「ls という小さなコマンドすら、ファイル一覧の取得や画面出力をすべてカーネル依頼で行っている」ことが見えます。
仕組みの直観 ── なぜこの設計か
- モードを分ける理由:信頼できないアプリにハードの全権を渡せない。最小権限の原則。ハード機構(モードビット)で強制するから、ソフトのバグでは破れない。
- システムコールを「窓口」に絞る理由:カーネルへの入口を限定すれば、そこで引数を検査し、不正な要求を弾ける。境界が1本なら守りやすい。
- trapで入る理由:通常の関数呼び出しではモードが変わらない。CPUの特別な機構(trap)を通すことで、安全にモードを切り替えつつ決められたハンドラへ入る。
⚠️ よくある誤解・落とし穴
- 「システムコールは普通の関数呼び出し」→ モード遷移を伴い、コストが高い(数百サイクル〜)。だから高頻度I/Oはバッファリング(バッファリング・キャッシュ・ジャーナリング)でまとめる。
- 「OS = カーネル」→ カーネルはOSの中核。シェルやライブラリ・ユーティリティもOSの一部。設計には モノリシック/マイクロカーネル の別がある。
- 「アプリが直接ハードを叩ける」→ ユーザモードでは不可。必ずカーネル経由。
- 「特権モードは速い」→ 速いのではなく権限が違うだけ。むしろ遷移コストがかかる。
対応ラボ
cs-foundations-study/labs/02-01_strace.md(Linux: strace ls でユーザコマンドが発行するシステムコール列を観察し、I/Oがすべてカーネル依頼であることを確認する手順)。
関連
- 次に プロセスとスレッド で、カーネルが管理する「実行単位」を見る
- CPUの配分は CPUスケジューリング
- メモリの仮想化(保護の実体)は 物理メモリと論理アドレス