最終更新:

OSのプロセス管理の仕組み — 音楽とブラウザーが一緒に動く理由


音楽とブラウザー:切り替えと並列

仕事を切り替える♪音楽の処理ブラウザーの処理1つの論理CPU♪Web♪Web同時に進む=同時に実行、とは限らない別のCPUでも進める♪音楽の処理ブラウザーの処理論理CPU 1論理CPU 2
CPUへの割り当てを表す理解用の例です。音楽の再生全体はバッファーやデバイス等も関わり、この時間割を固定で繰り返すわけではありません。
ひよこ ひよこ
音楽を聴きながらブラウザーを使えるのは、どうして?
ペンギン先生 ペンギン先生
OSがCPUを使う仕事の順番を決めているからだよ。複数の論理CPUで同時に実行することも、1つの論理CPUで仕事を切り替えることもある。通信やファイルの待ち時間には別の仕事を進められるんだ。
ひよこ ひよこ
プロセスって、アプリと同じこと?
ペンギン先生 ペンギン先生
実行中のプログラムを管理する単位だよ。プログラムが料理のレシピなら、プロセスは調理を進めている状態。ブラウザーのように1つのアプリが複数プロセスを使うこともあるから、アイコン1つとプロセス1つが必ず対応するわけではないんだ。
ひよこ ひよこ
動いているものを見分ける番号もある?
ペンギン先生 ペンギン先生
PIDというプロセスIDがあるよ。下のPythonの例では、親が子を1つ起動して、それぞれのPIDを表示する。番号は実行ごとに変わり、終了した番号が後で再利用されることもあるよ。
ひよこ ひよこ
スレッドは、その中の作業係なの?
ペンギン先生 ペンギン先生
そう考えると入りやすいね。同じプロセスのスレッドは、データやヒープなどを共有する一方、各スレッドは自分のスタックを持つ。共有データを同時に変更すると競合し得るので、同期が必要になるんだ。
ひよこ ひよこ
待っているプロセスもCPUを使い続ける?
ペンギン先生 ペンギン先生
OSが待機させた仕事は、通常その待ち時間にCPUを占有しないよ。準備ができて順番を待つことと、通信などの完了を待つことを分けよう。自分で繰り返し確認するビジーループとは違うんだ。
ひよこ ひよこ
切り替えると、前の仕事を忘れない?
ペンギン先生 ペンギン先生
実行を続けるためのレジスタなどの状態を保存し、次の仕事の状態を復元する。これがコンテキストスイッチだよ。切り替えには負担があり、時間はCPUやOS、負荷によって違うので、いつも何マイクロ秒とは言い切れないんだ。
ひよこ ひよこ
どの仕事も同じ時間ずつ回ってくるの?
ペンギン先生 ペンギン先生
方針や優先度で違うよ。ラウンドロビンは順番を理解する例だけど、Linuxの通常タスクの設計にはEEVDFなどがある。リアルタイム向けの方針も別にあり、どの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!

スレッドプールで仕事の渡し方を、メモリ管理で作業場所の分け方を確認できます。

参考資料