OSのプロセス管理の仕組み — 音楽とブラウザーが一緒に動く理由
音楽とブラウザー:切り替えと並列
まずは、親と子のPIDを表示する
音楽を再生しながらWebページを開けるのは、OSが実行する仕事と待っている仕事を管理しているためです。最初に、プログラムを起動することと、実行中のプロセスがあることを分けてみましょう。
Python 3が使えるなら、新しい練習用フォルダーにprocess-demo.pyを保存し、python process-demo.pyを実行します。既存のプロセスを停止する操作はありません。
import os
import subprocess
import sys
print("parent PID:", os.getpid())
child_code = "import os; print('child PID:', os.getpid())"
result = subprocess.run(
[sys.executable, "-c", child_code],
capture_output=True,
text=True,
check=True,
)
print(result.stdout.strip())
出力は、次のように2つの異なるPIDになります。1234と5678は説明用の番号です。
parent PID: 1234
child PID: 5678
親は子の終了を待ち、子が出した文字を受け取っています。PythonのsubprocessはOSごとのプロセス起動を扱う窓口です。Windowsで動かした結果から、Linuxで必ずforkが呼ばれた、と判断することはできません。
CPUの順番待ちと、通信の待ち時間は違う
| 場面 | 仕事の状態 |
|---|---|
| 計算を進めている | 実行中 |
| 計算できるがCPUの順番を待つ | 実行可能 |
| 通信やファイルなどの完了を待つ | 待機 |
これは理解用の分類です。Linuxの/procに表示されるR、S、Dなどと一対一の一覧ではありません。Rは実行中・実行可能、SやDは待ち方の違いを表します。
並行は複数の仕事を進行させること、並列は同じ時点に複数を実行することです。物理コアと論理CPUは同じ数とは限らず、SMTや仮想化の条件もあるため、「4コアなら最大4プロセス」とは数えません。
もう少し詳しく:管理と共有の境界
OSのスケジューラーは通常、実行するスレッド・タスクを選びます。コンテキストスイッチでは続きに必要な状態を保存・復元しますが、ユーザー空間とカーネル空間を行き来するたびに、別プロセスへ切り替わるわけではありません。
Linuxのforkは子プロセスを作り、exec系の操作はそのプロセスの実行内容を別プログラムへ置き換えます。forkのメモリはコピーオンライトで扱われ、最初からすべての物理ページを複製するわけではありません。
メモリの保護はCPUとOSの協力で行います。不正なアクセスでSIGSEGVが起きることはありますが、「別プロセスのアドレス値を使ったら必ず相手の領域へ届き、必ずこのエラーになる」という意味ではありません。共有メモリなど、明示した共有もあります。
動作が遅いときは、CPU使用率だけで決めず、待ち時間、メモリ、I/Oやロックも調べます。CPUが忙しいことと、スケジューラー自身が処理時間を使い切っていることは別です。
覚え方と次の一歩
「プロセス」って出てきたら「実行中のプログラムをOSが管理する単位」と思えばだいたいOK!
スレッドプールで仕事の渡し方を、メモリ管理で作業場所の分け方を確認できます。
参考資料
- Python:subprocess — 子プロセス起動、run、出力取得と終了コード
- Linux man-pages:pthreads(7) — スレッドで共有するメモリと個別スタック
- Linux man-pages:fork(2) — 子生成、別アドレス空間、コピーオンライト
- Linux man-pages:execve(2) — 現在のプロセスの実行内容を置換
- Linux man-pages:proc_pid_status(5) — R/S/D等の状態表示
- Linux kernel:EEVDF — 通常タスクのCPU配分と遅延の扱い