はじめに
Linuxにおけるプロセス管理は、システムを安定して運用するうえで欠かせない知識です。しかし、日々の業務ではアプリケーションやミドルウェアを操作する機会が多く、「Linuxがどのようにプロセスを生成し、CPUへ割り当て、実行・終了まで管理しているのか」を意識することは少ないかもしれません。
一方で、Linuxカーネルはプロセス管理を通じて、CPU時間やメモリなどの限られたリソースを効率よく各プログラムへ割り当てています。そのため、プロセス管理の仕組みを理解することは、CPU使用率の上昇や応答遅延、プロセスの異常終了など、実際の障害を調査・解析する際にも役立ちます。
本記事では、プロセスの基本的な概念から、fork・execによるプロセス生成の仕組み、プロセスの状態遷移を解説します。Linuxカーネルがどのようにプロセスを管理しているのかを理解し、実務に役立つ基礎知識を身につけていきましょう。
プロセスとは
プロセスとは実行中のプログラムを指します。ここで「実行中」とは、プログラムにメモリが割り当てられ、CPUによって命令が処理されている状態、またはCPUによる処理を待っている状態を意味します。
ではさっそく、Linuxマシン上で動作しているプロセスを確認してみましょう。Linuxサーバにてpsコマンド実行してみます。プロセス一覧を表示する際によく使われるオプションには、ps aux または ps -ef の2種類があります。用途に応じて使い分けてください。
• ps aux
CPU、メモリ使用率が確認可能です。%CPU、%MEMの項目を確認して下さい。
[root@appserver-dev ~]# ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 2.7 0.3 104968 13312 ? Ss 14:45 0:01 /usr/lib/systemd/systemd --switched-root --system --deserialize 31
root 2 0.0 0.0 0 0 ? S 14:45 0:00 [kthreadd]
root 3 0.0 0.0 0 0 ? S 14:45 0:00 [pool_workqueue_]
root 4 0.0 0.0 0 0 ? I< 14:45 0:00 [kworker/R-rcu_g]
root 5 0.0 0.0 0 0 ? I< 14:45 0:00 [kworker/R-sync_]
root 6 0.0 0.0 0 0 ? I< 14:45 0:00 [kworker/R-slub_]• ps -ef
親プロセス、子プロセスが確認可能です。PPIDという項目は親プロセスのPID(プロセスID)を指しています。
[root@appserver-dev ~]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 1 14:45 ? 00:00:01 /usr/lib/systemd/systemd --switched-root --system --deserialize 31
root 2 0 0 14:45 ? 00:00:00 [kthreadd]
root 3 2 0 14:45 ? 00:00:00 [pool_workqueue_]
root 4 2 0 14:45 ? 00:00:00 [kworker/R-rcu_g]
root 5 2 0 14:45 ? 00:00:00 [kworker/R-sync_]
root 6 2 0 14:45 ? 00:00:00 [kworker/R-slub_]• pstree
各プロセスの親子関係を視覚的に表現することも可能です。
[root@appserver-dev ~]# pstree -p
systemd(1)─┬─NetworkManager(693)─┬─{NetworkManager}(699)
│ └─{NetworkManager}(700)
├─agetty(735)
├─auditd(644)───{auditd}(645)
├─chronyd(686)
├─crond(733)
├─dbus-broker-lau(675)───dbus-broker(677)
├─firewalld(680)───{firewalld}(973)
├─httpd(725)─┬─httpd(751)
│ ├─httpd(754)─┬─{httpd}(757)
│ │ ├─{httpd}(758)
│ │ ├─{httpd}(759)
│ │ ├─{httpd}(760)
│ │ ├─{httpd}(761)※systemd(1)
現在のLinuxではPID 1としてsystemdが起動し、他の多くのプロセスの親となります。
プロセス管理の方法
プロセスの生成
Linuxにおいて新しいプログラムを実行するためには、カーネルに対してシステムコールを発行し、プロセスを作成する必要があります。一般的には、fork と exec というシステムコールを使ってプロセスを生成します。イメージは下図のようになります。

• fork
fork は親プロセスを複製して子プロセスを生成するシステムコールです。コピー元のプロセスを「親プロセス」、コピー先のプロセスを「子プロセス」と呼びます。親プロセスのファイルディスクリプタ、環境変数、ユーザIDなどの情報はそのままコピーされますが、子プロセスには新しいPID(Process ID)が割り当てられます。
• exec
execは現在のプロセスを指定したプログラムに置き換えるシステムコール群となります。PIDは変わりませんが、中身は完全に別のプログラムに置き換わります。
例えば、ユーザがlsコマンドを実行すると、シェルはforkで子プロセスを生成し、
その子プロセスがexecによってlsプログラムへ置き換わります。
※forkのコピー処理
実際には、親プロセスのメモリ全てを即座にコピーするのではなく、仮想メモリと物理メモリの対応関係を管理するページテーブルがコピーされます。そして、親プロセスまたは子プロセスがページテーブルを書き換えようとした時点で初めて実際のメモリコピーが行われます。この仕組みは「Copy On Write(COW)」と呼ばれています。この仕組みによって、メモリの使用量を節約し、オーバーヘッドを抑えてforkの処理速度を向上させることが可能となっています。
プロセスの状態遷移
プロセスが生成された後は、下図のような状態遷移を行います。

• プロセス生成
プロセスが生成されると、実行可能状態に遷移します。
• 実行可能状態
CPUリソースの割り当てを待っている状態となります。 CPUの実行権を得られたら実行状態に遷移します。コンテキストスイッチ(※)という仕組みにより、実行可能状態と実行状態を行き来する挙動となります。
• 実行状態
CPUが割り当てられ、処理が実行されている状態です。CPUが割り当てられた時間を経過すると、再び実行可能状態に遷移します。また、I/O待ちやリソースのロック待ちなどのイベントが発生すると、スリープ状態に遷移します。
• スリープ状態
イベント完了を待っている状態です。イベントが完了すると、実行可能状態に遷移します。
• プロセス終了
プログラムの処理が終わって、exitシステムコールが呼ばれるとプロセスが終了します。あるいはシグナルを使って強制的に終了させることもできます。
• ゾンビ状態
プロセスが終了した後、親プロセスが終了ステータスを取得(wait)しない場合、カーネルにプロセス情報が残った状態になります。これをゾンビ状態と呼びます。原因としては、プログラムのバグなどで親がwaitを行わないケースが挙げられます。
※コンテキストスイッチとは
論理CPU上で動作するプロセス、スレッドを切り替えることをコンテキストスイッチと呼びます。タイムスライスの時間が到来すると問答無用でコンテキストスイッチが発生して他の処理にCPUが使われます。Linuxにおけるコンテキストとは主にCPUレジスタの情報となります。実行中のプロセスを別のプロセスに切り替える際、現在のプロセスのコンテキストを保存し、次のプロセスの情報を復元します。
プロセス制御
シグナルによるプロセス制御
シグナルとは、プロセス間通信を行う際に使用される信号のことです。シグナルを受け取ったプロセスは、シグナルの指示に応じた処理を行います。良く使うシグナルとしては、下記のようなものがあります。
• SIGINT(シグナル番号:2)
プロセスに「割り込み」を要求するシグナルであり、デフォルトではプロセスが停止されます。コンソール操作時にキーボードから「Ctrl + c」と打つと送信されるシグナルです。ただし必ずプロセスが中断されるというわけではなく、プロセスがSIGINTを無視する設定になっていたり、SIGINTを受けて独自ロジックを実行するような設定になっている場合、プロセスが中断されないケースがあります。
• SIGTERM(シグナル番号:15)
プロセスを終了するシグナルです。シグナルの種類がオプションに指定されていない場合、デフォルトでは本シグナルが送信されます。
• SIGKILL(シグナル番号:9)
プロセスを即座に強制終了するシグナルです。SIGTERMで終了できなかった場合、本シグナルを送信して停止するケースがあります。kill -9 <PID>という形でコマンド実行するので「キルナイン」と呼んだりします。
※ゾンビプロセスはすでにプロセスが終了している状態なので、SIGKILLでも消すことはできません。親プロセスを終了させることでPID:1のinitに引き取らせたり、親プロセスにwait()を実行させることで削除します。
まとめ
本記事では、Linuxにおけるプロセス管理の仕組みについて解説しました。
プロセスの基本的な概念から、fork・execによるプロセス生成、プロセスの状態遷移、コンテキストスイッチ、シグナルによるプロセス制御まで、一連の流れを見てきました。
Linuxカーネルは、多数のプロセスを効率よく管理し、限られたCPUリソースを各プロセスへ適切に割り当てることで、システム全体の性能と安定性を維持しています。そのため、これらの仕組みを理解しておくことで、CPU使用率の上昇やプロセスの異常終了、応答遅延などの障害が発生した際にも、原因を論理的に切り分けられるようになります。
普段の運用では内部動作を意識する機会は少ないかもしれませんが、Linuxをより深く理解するうえでプロセス管理は欠かせない知識です。本記事が、Linuxカーネルの仕組みや障害調査を学ぶきっかけになれば幸いです。
Linuxの全体像について知りたい方は、以下の記事もぜひご覧ください。
▶ インフラエンジニア入門|Linuxの歴史・機能概要・特徴をわかりやすく解説
https://eeengineer.com/linux-overview/
参考文献



コメント