目標

「プロセス」の概要を理解する。
「プロセスID」について概要を理解する。
「プロセスの親子関係」について概要を理解する。
「子プロセスの生成」について概要を理解する。
「ジョブ」「セッション」について概要を理解する。
「フォアグラウンドジョブ」「バックグラウンドジョブ」について概要を理解する。

プロセス

プロセスの概要

プロセスとは

Linuxでは動作中のプログラムのことをプロセスといいます。これは、「実行状態」「待ち状態」「実行可能状態」のいずれかの状態で、CPUの管理下にある処理単位です。

実行される前のプログラム(実行後はこれがプロセスとなります。)は実行ファイルとしてHDDなどの記憶媒体に保管されています。必要なプログラムを呼び出すと、関連する実行ファイル(コマンドやアプリケーション)がメモリ上に展開されてプロセスとして生成され、実行可能状態になります。

ディスパッチ:スケジューラが、実行可能状態のプロセスの中から1つを選び、CPUに割り当てて実行状態に移す処理のことをディスパッチといいます。これは、プロセスが実際にCPUで動き出す瞬間を指します。

プリエンプション:現在CPUを使用しているプロセスよりも優先度の高いプロセスが現れた場合、OSが現在のプロセスを中断させ、CPUの使用権を奪って別のプロセスに切り替える処理をプリエンプションといいます。中断されたプロセスは再び実行可能状態に戻ります。また、このように、CPUがあるプロセスの実行を停止し、別のプロセスの実行を開始する切り替え処理をコンテキストスイッチと呼びます。

出力処理の代表例として、プリンターによる印刷があります。通常、「PCからのデータ送信」と「プリンターでの印刷」はひとまとまりの作業ですが、印刷には時間がかかるため、複数の印刷要求があると、CPUは次の出力を送る前にプリンターの処理完了を待つ必要があります(=実行待ち状態)。

しかし、CPUを待機させ続けるのは非効率です。そこで用いられるのがスプーリング(Spooling)です。スプーリングは、印刷データを一時的に補助記憶装置(ディスクなど)に保存しておき、プリンター側が自分のタイミングでデータを読み取って出力します。

このようにすることで、CPUは印刷待ちの間に他の処理を並行して実行できるようになり、スループット(単位時間あたりの処理量)が向上します。

プロセスは次の順で準備(プロセスの生成→実行可能状態)が行われます。

  1. プロセステーブルへのエントリ
    • カーネルは新しいプロセスのために、プロセステーブル(Process Table)にエントリを作成します。ここには、プロセスID(PID)や親プロセスID(PPID)、プロセスの状態、優先度などの情報が格納されます。
  2. メモリブロックへの割り当て(プロセステーブルへブロック情報追加)
    • プロセスに対して必要な仮想メモリ空間が確保されます。コード領域、データ領域、スタック領域などが割り当てられます。
  3. プログラムファイルの展開(プログラムカウンターへ最初のプロセスを登録)
    • 指定された実行ファイル(バイナリプログラム)がメモリにロードされ、プログラムカウンタ(PC)はプログラムのエントリポイントに設定されます。これにより、CPUはどこから実行を開始するかを知ることができます。
  4. プロセス状態の設定
    • 準備が完了したプロセスは、「実行可能状態(Ready)」となり、スケジューラによってCPUに割り当てられるのを待ちます。

プロセステーブル(Process Table)は、実行中または実行待ち状態のプロセスに関する情報を管理するデータ構造であり、各プロセスのID、状態、優先度、使用中のリソース、メモリ情報などのプロパティを保持しています。

プロセスID

プロセスにはプロセスIDといった重複しない整数が割り当てられてプロセステーブルで管理されます。プロセスIDは「PID」 (プロセス識別子)といってプロセスを区別するために利用されます。

プロセスの親子関係

プロセスは別のプロセスの生成を行うことがあります。この時、生成する側を「親プロセス」、生成される側を「子プロセス」といいます。(※プロセスの生成にはメモリの割り当てなどが必要なため、そのような処理はカーネルに依頼します。)

プロセスが生成されると子プロセスは親プロセスのIDを持っていて、親子関係が分かるようになっています。親プロセスのIDをPPID(Parent PID)といいます。

カーネルはLinuxそのものを指します。シェルやそれ以外のプログラムはカーネルの上に載っているソフトウェアとなります。

子プロセスの生成順序について

プロセスはページテーブルという「仮想的なアドレス」と「物理的なアドレス」を紐づけるテーブルを利用して処理を行います。

親プロセスは子プロセスを生成する時fork()関数を利用します。

fork()関数

Linuxでは、プロセスが別のプロセス(子プロセス)を生成する際に、fork()関数を使用します。このとき、親プロセスのページテーブルのエントリが複製され、親と子は同じ物理メモリページを読み取り専用として共有します。

※この時点ではメモリを共有しています。

その後、親または子が共有されているメモリページに書き込みを試みると、そのページは書き込み禁止であるため、保護違反によるページフォールトが発生します。

※この時点ではメモリを共有しています。

このとき、CPUはカーネルモードに切り替わり、次の処理を行います。

  1. 該当する物理メモリページの新しいコピーを確保
  2. 書き込みを行おうとしていたプロセスのページテーブルを更新し、そのページを新しい物理ページにマッピング
  3. 新しいページに書き込み可能属性を設定

これにより、親子プロセスは同一の内容を持ちつつも、独立したメモリページを使うことができます。

※この時点では別々のメモリを確保しています。

その後、カーネルモードでの処理を終えると処理はプロセス(ユーザーモード側)へ戻されます。

execve()関数

fork()関数で作成した子プロセスは親プロセスのコピーとなっています。このあと、子プロセスではexecve()関数を利用して別のプログラムと置き換えを行います。

親子関係のあるプロセスでは、子プロセスの終了処理が正しく行えない問題が発生することがあります。通常、親子関係のあるプロセスでは、子プロセスが先に終了します。子プロセスが終了すると、その終了を知らせるシグナル(SIGCHLD)が親プロセスに送られます。親プロセスはこのシグナルを受け取ることで、子プロセスの終了を検知し、「後始末」(すなわち、wait() などを使ってプロセスの終了ステータスを回収する処理)を行います。

※子プロセスが終了したが、親プロセスがまだ後始末をしていない状態を「ゾンビ状態」といいます。この状態のプロセスを「ゾンビプロセス」と呼びます。

仮に、何らかの理由で親プロセスが子プロセスの後始末を行わない場合、子プロセスは終了していてもプロセステーブル上に残り、メモリや PID を占有し続けることになります。これがゾンビプロセスです。

ジョブ

ジョブとセッションの概要

ジョブとは

1つ以上のプロセスをもつ「処理のあつまり」のことをジョブといいシェルで制御できます。単位としては、ひとつのコマンド処理もひとつのジョブ。パイプでつないだ複数のコマンド処理もひとつのジョブとなります。

プロセスグループ…プロセスグループは、複数のプロセスをひとまとめにした単位で、一般的には「ジョブ」と同じ意味合いで扱われることがあります。
シェルはジョブごとにプロセスグループID(PGID)を割り当て、シグナルの送信や制御をグループ単位で行います。

セッションとは

Linux において「セッション」とは、ユーザーが端末や SSH などを通じてログインした際に対応する、一連のプロセスのまとまりを指します。各セッションには一意の「セッション ID(SID)」が割り当てられます。

セッションの中には複数のプロセスグループが含まれることができます。つまり、1つのログインセッション内で複数のジョブ(プロセスグループ)を管理することが可能です。

セッションリーダーとは、そのセッションを最初に開始したプロセスのことを指します。たとえば、シェル(bash や zsh など)がセッションリーダーになることが多いです。セッションリーダーとなるプロセスは、自身のプロセス ID(PID)をセッション ID(SID)として持ちます。

「フォアグラウンドジョブ」と「バックグラウンドジョブ」

フォアグラウンドジョブ

各セッション(1ユーザーが利用する1端末)に対して1つだけ存在することができるジョブです。基本的なコマンド入力がフォアグラウンドジョブとなります。

フォアグラウンドジョブは入力したコマンドの全ての処理が完了するまで、別のコマンドを受け付けなくなります。シェルを占有した操作と言えます。

ジョブには「フォアグラウンドジョブ」「バックグラウンドジョブ」「サスペンドジョブ」があり「サスペンドジョブ」はフォアグラウンドジョブが「Ctrl+Z」で一時的に止められたジョブのことを指します。

バックグラウンドジョブ

キーボードを利用したコマンド入力にバックグラウンドジョブを指定したジョブをバックグラウンドジョブといいます。コマンドの後に「スペース + &」を入力します。

この時、シェルはこのジョブをバックグラウンドジョブとして管理します。バックグラウンドジョブとして動くジョブはジョブ内のひとつひとつのプロセスの処理の終了を制御しません。全てのプロセスが終了するまで動き続けます。

今回は以上になります。

「Linux」おすすめ書籍6選【初心者・脱初心者用】| 現役エンジニア&プログラミングスクール講師「Linux」初心者の方がLinuxの操作や仕組みを理解するためのお勧めの書籍について取り上げています。また中級者として更に進んだ学習ができる書籍についても1冊取り上げています。ページの下部には「おすすめのITスクール情報」「おすすめ求人サイト」について情報を掲載中。...

ブックマークのすすめ

「ほわほわぶろぐ」を常に検索するのが面倒だという方はブックマークをお勧めします。ブックマークの設定は別記事にて掲載しています。

「お気に入り」の登録・削除方法【Google Chrome / Microsoft Edge】「お気に入り」の登録・削除方法【Google Chrome / Microsoft Edge】について解説している記事です。削除方法も掲載しています。...
【パソコン選び】失敗しないための重要ポイント | 現役エンジニア&プログラミングスクール講師【パソコン選び】失敗しないための重要ポイントについての記事です。パソコンのタイプと購入時に検討すべき点・家電量販店で見かけるCPUの見方・購入者が必要とするメモリ容量・HDDとSSDについて・ディスプレイの種類・バッテリーの持ち時間や保証・Officeソフト・ウィルス対策ソフトについて書いています。...