プログラムの実行中のすべてのインスタンスは、プロセスと呼ばれます。プロセスの概念は、UNIX / Linux オペレーティング システムの基本です。プロセスには、PID またはプロセス ID の形式で独自の ID があります。各プロセスのこの PID は、オペレーティング システム全体で一意です。また、各プロセスには、コードセグメント、データセグメント、スタックセグメントなどのメモリセグメントが配置される独自のプロセスアドレス空間があります。プロセスの概念は非常に広く、プロセスの作成、プロセスの実行、プロセスの終了に大別できます。
Linux プロセス シリーズ:パート 1、パート 2、パート 3、パート 4 (この記事)。
この記事では、プログラミングの観点からプロセス作成の側面に集中します。 fork() 関数に焦点を当て、その仕組みを理解します。
fork() 関数
fork() 関数は、呼び出し元の既存のプロセスを複製して新しいプロセスを作成するために使用されます。この関数が呼び出された既存のプロセスが親プロセスになり、新しく作成されたプロセスが子プロセスになります。すでに述べたように、子は親の複製コピーですが、いくつかの例外があります。
- オペレーティング システムで実行されている他のプロセスと同様に、子プロセスには一意の PID があります。
- 子には、それを作成したプロセスの PID と同じ親プロセス ID があります。
- リソースの使用率と CPU 時間のカウンターが子プロセスでゼロにリセットされます。
- 子の保留中のシグナルのセットが空です。
- 子は親からタイマーを継承しません
上記のリストは網羅的なものではないことに注意してください。 fork() の man ページには、非常に多くのポイントが記載されています。この記事の読者には、fork() 関数のマニュアル ページでこれらのポイントを確認することを強くお勧めします。
戻り型
Fork() は、呼び出し元のメソッドに戻るときに興味深い動作をします。 fork() 関数が成功すると、2 回戻ります。戻り値「0」で子プロセスに戻ると、子の PID を戻り値として親プロセスに戻ります。この動作は、フォークが呼び出されると子プロセスが作成され、子プロセスがテキスト セグメントを親プロセスと共有し、同じテキスト セグメント内の次のステートメントから実行を継続するため、フォークが 2 回戻るためです(親で 1 回)。子に 1 回)。
C フォークの例
fork 関数の使用法を示す例を見てみましょう。
#include <unistd.h> #include <sys/types.h> #include <errno.h> #include <stdio.h> #include <sys/wait.h> #include <stdlib.h> int var_glb; /* A global variable*/ int main(void) { pid_t childPID; int var_lcl = 0; childPID = fork(); if(childPID >= 0) // fork was successful { if(childPID == 0) // child process { var_lcl++; var_glb++; printf("\n Child Process :: var_lcl = [%d], var_glb[%d]\n", var_lcl, var_glb); } else //Parent process { var_lcl = 10; var_glb = 20; printf("\n Parent process :: var_lcl = [%d], var_glb[%d]\n", var_lcl, var_glb); } } else // fork failed { printf("\n Fork failed, quitting!!!!!!\n"); return 1; } return 0; }
上記のコードでは:
- 値「0」で宣言および初期化されたローカル変数およびグローバル変数(var_lcl および var_glb )
- 次に fork() 関数が呼び出され、その戻り値が変数 childPID に保存されます。
- ここで、childPID の値がチェックされて、fork() 関数が渡されたことを確認します。
- 次に、childPID の値に基づいて、親子のコードが実行されます。
- 変数 var_lcl と var_glb が使用される理由は何ですか?
- 子プロセスと親プロセスの両方がこれらの変数の別々のコピーで動作することを示すために使用されます。
- 上記の事実を示すために、これらの変数の個別の値が使用されます。
- Linux では、コピー オン ライト メカニズムが使用されます。この場合、子と親のいずれかが変数の値を変更しようとするまで、変数の同じコピーで作業を続けます。
- fork の後、子が最初に実行されるか、親が最初に実行されるかは、スケジューラによって異なります。
さて、上記のコードをコンパイルして実行すると:
$ ./fork Parent process :: var_lcl = [10], var_glb[20] Child Process :: var_lcl = [1], var_glb[1]
上記の出力では、子プロセスと親プロセスの両方が実行され、ログに var_lcl と var_glb の個別の値が示されていることがわかります。これは、親と子の両方が var_lcl と var_glb の独自のコピーを持っていると結論付けます。
注:関数 getpid() を使用して呼び出しプロセスのプロセス ID を取得でき、関数 getppid() を使用して親プロセスの PID を取得できます。