プロセスの複製と終了

すべてのプロセスには少なくとも 1 つのスレッドがあるので、 プロセスの作成 (すなわち、複製) と終了には、スレッドの作成と終了を伴います。

この項では、プロセスの複製および終了時のスレッドとプロセスの間の対話について説明します。

プロセスの複製と終了について、次のセクション以降でさらに詳しく説明します。

フォーク

プログラマーは、以下の場合に fork サブルーチンを呼び出します。

  • 同じプログラム内に、新しい制御のフローを作成するため。 AIX®は新しいプロセスを作成する。
  • 異なるプログラムを実行する、新しいプロセスを作成するため。 この場合、 fork サブルーチンへの呼び出しの直後に、 exec サブルーチンの 1 つへの呼び出しが続きます。

マルチスレッド・プログラムでは、新しい制御フローを作成する fork サブルーチンの最初の使用は、 pthread_create サブルーチンによって提供されます。 したがって、fork サブルーチンは、 新しいプログラムの実行のみに使用すべきです。

fork サブルーチンは親プロセスを複製しますが、 コール側のスレッドだけを複製し、子プロセスは単一スレッド・プロセスです。 親プロセスのコール側のスレッドは、子プロセスの初期スレッドになります。 これは、親プロセスの初期スレッドでない場合もあります。 そのため、子プロセスの初期スレッドがそのエントリー・ポイント・ルーチンから戻ると、子プロセスは終了します。

親プロセスを複製すると、fork サブルーチンは、その状態を含むすべての同期変数も複製します。 したがって、例えば mutex が子プロセス内の既に存在しないスレッドによって保留され、 それと関連するリソースが不整合になっている場合があります。

fork サブルーチンは、新規プログラムの実行のためだけに使用すること、 および子プロセス内の fork サブルーチンに対する呼び出しの後に、 できるかぎり早く exec サブルーチンの 1 つを呼び出すことを強くお勧めします。

fork ハンドラー

上記の fork 規則は、マルチスレッド・ライブラリーの要件に対応していません。 アプリケーション・プログラムは、マルチスレッド・ライブラリーが使用中であることに気付かず、従来と同様に、fork サブルーチンと exec サブルーチンの間で任意の数のライブラリー・ルーチンを呼び出します。 実際に、これらは古い単一スレッド・プログラムであるために、 スレッド・ライブラリーによる新しい制約に従うことは期待できません。

他方では、マルチスレッド・ライブラリーには、後で子プロセスでルーチンが呼び出された場合に、fork 中の内部状態を保護するための方法が必要です。 特に、fork サブルーチンと exec サブルーチンの間で入出力の宛先を変更するために呼び出されることが多い、マルチスレッド入出力ライブラリーで問題が発生します。

pthread_atfork サブルーチンは、 fork サブルーチンを呼び出す無害なアプリケーション・プログラムからマルチスレッド・ライブラリーを保護する方法を提供します。 また、ライブラリー・ルーチンまたはアプリケーション自体の中の fork サブルーチンに対する呼び出しから保護するための標準メカニズムを、マルチスレッドのアプリケーション・プログラムに対して提供します。

pthread_atfork サブルーチンは、 fork サブルーチンに対する呼び出しの前後に呼び出す fork ハンドラーを登録します。 fork ハンドラーは、fork サブルーチンを呼び出したスレッドで実行されます。 次の fork ハンドラーが存在します。
サブルーチン 説明
準備 prepare fork ハンドラーは、fork サブルーチンの処理が始まる直前に呼び出されます。
parent fork ハンドラーは、親プロセスにおける fork サブルーチンの処理が完了した直後に呼び出されます。
Child child fork ハンドラーは、子プロセスにおける fork サブルーチンの処理が完了した直後に呼び出されます。

プロセスの終了

prepare fork ハンドラーは、後入れ先出し (LIFO) 順で呼び出されますが、 これに対して、親と子の fork ハンドラーは先入れ先出し (FIFO) 順で呼び出されます。 これによって、プログラムは希望のロック順序を保つことができます。

exitatexit、または _exit サブルーチンを明示的または暗黙的に呼び出すことによってプロセスが終了すると、プロセス内のすべてのスレッドが終了します。 クリーンアップ・ハンドラーとスレッド固有データ・デストラクターは、 いずれも呼び出されません。
注: unatexit サブルーチンは、 atexit サブルーチンによって以前に登録された関数を登録解除します。 参照された関数が見つかると、その関数は、通常のプログラム終了で呼び出される関数 のリストから除去されます。

このような振る舞いをする理由は、すべてのスレッドを含むプロセス全体が終了し、 すべてのスレッド固有ストレージを含むすべてのプロセス・ストレージが再利用されるので、 クリーンなままにしておく状態はなく、また再利用するスレッド固有ストレージもないためです。