Linuxのプロセス管理の仕組みを徹底理解する

Linuxのプロセス管理の仕組みを徹底理解する

Linuxのプロセス管理は、サーバー運用、アプリケーション開発、障害調査、パフォーマンス改善のどれにおいても中心になる基礎知識の1つになる。Webサーバーが起動する仕組み、バックグラウンドジョブが残る理由、CPUを消費している犯人の見つけ方、killしても止まらない理由、親子関係やゾンビプロセスの意味などは、すべてプロセス管理の理解とつながっている。単に pskill を覚えるだけでは足りず、「Linuxがプロセスをどう作り、どう切り替え、どう終了させ、どう回収するか」を流れで押さえると、日常的なトラブル対応がかなり速くなる。

プロセスとは何か

Linuxでいうプロセスは、単なるプログラムのファイルではなく、「実行中のプログラムそのもの」を指す。
たとえば、/usr/bin/python3 というファイルはプログラムだが、それを起動して実際にメモリ上で動いている状態がプロセスになる。
同じプログラムを3回起動すれば、ファイルは1つでもプロセスは3つ存在する。
つまり、プロセスは「実行単位」であり、PID、メモリ空間、ファイルディスクリプタ、環境変数、現在の状態などを持った生きている対象として考えると分かりやすい。

プロセスとプログラムの違い

この2つは混同されやすい。
・プログラムはディスク上の実行ファイル
・プロセスはそのプログラムが実行中の状態
たとえば nginx という実行ファイルがあり、それを起動すると master process と worker process が複数動くことがある。このとき、プログラムは1種類でも、プロセスは複数存在する。
Linuxの調査で見る対象は、多くの場合プログラムではなくプロセスになる。

PIDとPPIDの意味

Linuxでは、各プロセスにPID(Process ID)が割り当てられる。
これはプロセスを識別するための番号。
さらに、PPID(Parent Process ID)はそのプロセスを作った親プロセスのPIDになる。
つまり、Linuxのプロセスは親子関係を持っている。

ps -ef

この一覧で、
・PID
・PPID
・CMD
を見ると、どのプロセスがどの親から起動されたかを追いやすい。
親子関係は、サービスの起動経路やゾンビ化の原因を調べるときに重要になる。

プロセスはどう作られるのか

Linuxでは、新しいプロセスは基本的に既存のプロセスから作られる。
大まかな流れとしては、

  1. 親プロセスが子プロセスを生成する
  2. 子プロセスが必要に応じて別のプログラムへ切り替わる
    という形になる。
    そのため、Linuxでは「いきなり無からプロセスが生まれる」というより、「親から子が派生する」という見方の方が実態に近い。
    シェルからコマンドを打つと、そのシェルが新しいプロセスを起動していると考えると分かりやすい。

プロセスの親子関係を見る方法

親子関係を木構造で見ると、理解がかなり進みやすい。
そのとき便利なのが pstree

pstree -p

これを使うと、
・systemd
・sshd
・bash
・実行中のコマンド
といった流れが木構造で見える。
どのプロセスがどこから起動されたのかを視覚的に追えるため、サービス調査やバックグラウンドジョブの理解に役立つ。

プロセスの状態には種類がある

Linuxのプロセスは、常に「実行中」だけではない。
代表的な状態としては次のようなものがある。
・実行中
・実行待ち
・スリープ中
・停止中
・ゾンビ
ps で状態を見るには STAT 列が参考になる。

ps aux

たとえば、
R は実行中または実行可能
S はスリープ
T は停止
Z はゾンビ
といった形で表示されることがある。
障害調査では、この状態が非常に重要になる。

ゾンビプロセスとは何か

ゾンビプロセスは、処理自体は終了しているが、親プロセスが終了状態を回収していないためにプロセステーブル上に残っている状態を指す。
CPUや通常のメモリを大きく食い続けるわけではないが、大量に残ると異常のサインになる。
ps auxZ 状態が見えたら、子そのものより親プロセス側の挙動を疑う方が本質に近い。
つまり、ゾンビを見つけたら「誰がそれを回収すべきなのか」を見る必要がある。

LinuxはどうやってCPUをプロセスへ割り当てるのか

CPUは1つの瞬間には限られた数の処理しか実行できないため、Linuxは短い単位でプロセスを切り替えながら複数の処理を進めている。
この切り替えによって、複数のプロセスが同時に動いているように見える。
これを理解すると、
・CPU使用率が高い
・プロセス数が多い
・レスポンスが悪い
といった現象を見たときに、「今どのプロセスがCPU時間を多く取っているのか」という発想がしやすくなる。

フォアグラウンドとバックグラウンドの違い

シェルから見たとき、プロセスにはフォアグラウンド実行とバックグラウンド実行がある。
フォアグラウンドは、端末を占有してその場で操作する実行形態。
バックグラウンドは、端末の裏側で動かし、プロンプトを返す実行形態。

python app.py &

この & はシェル上のジョブ制御としてバックグラウンドへ回しているだけであり、systemdのようなサービス管理とは別物。
そのため、端末終了時の挙動やログの扱いは別途考える必要がある。

ジョブ制御とプロセス管理の違い

初心者が混同しやすいのがここ。
ジョブ制御は、主にシェルが「今この端末で起動した処理」を管理する仕組み。
一方、プロセス管理はLinux全体が持っている仕組みになる。
たとえば次のコマンドはシェルのジョブ制御寄り。

jobs
bg
fg

一方、こちらはLinux全体のプロセスを見るコマンド。

ps -ef
top
kill 1234

同じ「実行中のもの」を扱っているように見えても、見ている範囲が違う。

プロセス一覧を見る基本コマンド

Linuxでプロセスを見る基本コマンドは pstop
ps はスナップショットとして一覧を見るのに向いている。
top はリアルタイムで動きを見るのに向いている。

ps -ef

top

たとえば、
・今どんなプロセスがいるか → ps
・どれがCPUを食っているか → top
という使い分けが分かりやすい。
障害対応ではこの2つを最初に開くことが非常に多い。

特定のプロセスを探す方法

大量のプロセスがある中で、特定のものだけ見たいことも多い。
その場合は grep と組み合わせる。

ps -ef | grep nginx
ps -ef | grep php-fpm
ps -ef | grep python

より直接的には pgrep も便利。

pgrep nginx
pgrep -a python

これで、対象のPIDを素早く見つけやすくなる。
killや詳細調査に進む前段階としてかなり使いやすい。

プロセスを終了させる方法

プロセスを止めるときに使うのが kill
ただし、名前の印象と違って「必ず強制終了するコマンド」ではなく、シグナルを送るコマンドとして理解した方が正確。

kill 1234

これは多くの場合、終了依頼に近いシグナルを送る。
それでも止まらない場合に強制寄りの方法を使う。

kill -9 1234

ただし、いきなり -9 を使うと、
・後処理できない
・一時ファイルが残る
・データ破損のリスクがある
といった問題がある。
まずは通常の kill で止まるかを見る方が安全。

シグナルの考え方を理解する

Linuxのプロセス制御を理解するうえで、シグナルはかなり重要。
シグナルは、プロセスへ「終了してほしい」「一時停止してほしい」「再読込してほしい」などの通知を送る仕組み。
たとえば代表的なものとして、
・TERM
・KILL
・HUP
・INT
がある。
サービス再読込や安全停止をしたいときは、単純にプロセスを殺すのではなく、シグナルをどう扱うかが重要になる。

確認には次のような方法もある。

kill -l

systemdとプロセス管理の関係

今のLinuxでは、多くのディストリビューションで systemd がPID 1として動いており、サービス管理の中心になっている。
つまり、サーバー起動直後から多くのプロセスは systemd 配下で管理される。
そのため、単なる pskill だけでなく、サービスとして扱うなら systemctl を使う方が正しいことが多い。

systemctl status nginx
systemctl status mysql
systemctl restart php8.2-fpm

サービスプロセスは「ただの1プロセス」ではなく、起動、停止、再起動、依存関係、自動起動まで含めて systemd 管理下にあると考える方が実務では分かりやすい。

プロセスとスレッドの違い

調査していると、プロセスとスレッドの違いも重要になる。
ざっくり言うと、
・プロセスは独立した実行単位
・スレッドはその中の実行の流れ
となる。
マルチスレッドアプリでは、1つのプロセスの中で複数の処理が並んで動く。
そのため、「PIDは1つなのにCPUをすごく使っている」ということも起きる。
Javaや一部のPython、データベース、Webサーバーの調査では、この視点が重要になる。

よくあるトラブルと原因の見方

Linuxのプロセス管理でよく遭遇する問題はかなり典型的。
・CPUを使い切るプロセスがある
・メモリが増え続ける
・killしてもすぐ再起動する
・ゾンビが残る
・ポートが使用中で新しく起動できない
・バックグラウンドジョブがSSH切断後に消える
たとえば「killしても復活する」なら、プロセス自身ではなく systemd や supervisor、cron が再起動している可能性がある。
つまり、現象だけでなく“誰がそのプロセスを生かしているか”を見ることが大切になる。

調査の初動で使いやすい手順

プロセスまわりで何か問題が起きたとき、進めやすい順番は次の流れ。

  1. top で全体を見る
  2. ps -ef で対象を探す
  3. pstree -p で親子関係を見る
  4. systemctl status でサービス管理か確認する
  5. 必要なら killsystemctl restart を使う
    この順で進めると、「単独プロセスなのか」「サービス管理下なのか」「親が誰なのか」を比較的スムーズに追いやすい。

まとめ

Linuxのプロセス管理を理解するうえで重要なのは、
・プロセスは実行中のプログラムであること
・PIDとPPIDで親子関係があること
・状態には実行中だけでなくスリープやゾンビもあること
・ジョブ制御とシステム全体のプロセス管理は別であること
・killは単なる強制削除ではなくシグナル送信であること
・サービス運用ではsystemdが中心になること
このあたりを流れで押さえることになる。
単にコマンドだけ覚えるより、「Linuxがどうやってプロセスを生かし、止め、回収しているか」を理解すると、障害対応、パフォーマンス調査、サーバー運用の精度がかなり上がりやすい。