logo

C の fork()

Fork システム コールは、Linux および Unix システムで新しいプロセスを作成するために使用されます。 子プロセス 、fork() 呼び出しを行うプロセス (親プロセス) と同時に実行されます。新しい子プロセスが作成されると、両方のプロセスが fork() システム コールに続いて次の命令を実行します。

子プロセスは、親プロセスで使用するものと同じ pc (プログラム カウンタ)、同じ CPU レジスタ、および同じオープン ファイルを使用します。パラメーターは取らず、整数値を返します。



以下は、fork() によって返されるさまざまな値です。

  • 負の値 : 子プロセスの作成に失敗しました。
  • ゼロ : 新しく作成した子プロセスに戻ります。
  • 正の値 : 親または呼び出し元に返されます。値には、新しく作成された子プロセスのプロセス ID が含まれます。

フォークプロセスの作成

注記: fork() はスレッドベースの関数であり、正しい出力を取得するには、ローカル システムでプログラムを実行します。



上記のプログラムは Windows 環境ではコンパイルできないことに注意してください。

C の fork() の例

C




c 文字列の配列



#include> #include> #include> int> main()> {> > >// make two process which run same> >// program after this instruction> >pid_t p = fork();> >if>(p<0){> >perror>(>'fork fail'>);> >exit>(1);> >}> >printf>(>'Hello world!, process_id(pid) = %d '>,getpid());> >return> 0;> }>

>

>

出力

Hello world!, process_id(pid) = 31 Hello world!, process_id(pid) = 32>

例 2: hello が出力される回数を計算します。

C




#include> #include> #include> int> main()> {> >fork();> >fork();> >fork();> >printf>(>'hello '>);> >return> 0;> }>

>

>

出力

hello hello hello hello hello hello hello hello>

説明

「hello」が出力される回数は、作成されたプロセスの数と同じです。プロセスの合計数 = 2nここで、n は fork システム コールの数です。したがって、ここでは n = 3, 23= 8 3 つの行にいくつかのラベル名を付けてみましょう。

fork (); // Line 1 fork (); // Line 2 fork (); // Line 3 L1 // There will be 1 child process /  // created by line 1. L2 L2 // There will be 2 child processes /  /  // created by line 2 L3 L3 L3 L3 // There will be 4 child processes // created by line 3>

したがって、合計 8 つのプロセス (新しい子プロセスと 1 つの元のプロセス) があります。プロセス間の関係をツリー階層として表現したい場合は、次のようになります。 メインプロセス: P0 1 番目のフォークによって作成されたプロセス: P1 2 番目のフォークによって作成されたプロセス: P2、P3 3 番目のフォークによって作成されたプロセス: P4、P5、P6、P7

 P0 / |  P1 P4 P2 /   P3 P6 P5 / P7>

例 3: 次のプログラムの出力を予測します。

C




#include> #include> #include> #include> void> forkexample()> {> >pid_t p;> >p = fork();> >if>(p<0)> >{> >perror>(>'fork fail'>);> >exit>(1);> >}> >// child process because return value zero> >else> if> ( p == 0)> >printf>(>'Hello from Child! '>);> > >// parent process because return value non-zero.> >else> >printf>(>'Hello from Parent! '>);> }> int> main()> {> >forkexample();> >return> 0;> }>

>

>

出力

Hello from Parent! Hello from Child!>

注記: 上記のコードでは、子プロセスが作成されます。 fork() は、子プロセスでは 0 を返し、親プロセスでは正の整数を返します。ここでは、親プロセスと子プロセスが同時に実行されているため、2 つの出力が可能です。したがって、OS が最初に親プロセスに制御を与えるのか、それとも子プロセスに制御を与えるのかはわかりません。

親プロセスと子プロセスは同じプログラムを実行していますが、それはそれらが同一であることを意味するわけではありません。 OS はこれら 2 つのプロセスに異なるデータと状態を割り当て、これらのプロセスの制御フローは異なる場合があります。次の例を参照してください。

例 4: 次のプログラムの出力を予測します。

C




VLCでYouTubeビデオをダウンロード

#include> #include> #include> #include> > void> forkexample()> {> >int> x = 1;> >pid_t p = fork();> >if>(p<0){> >perror>(>'fork fail'>);> >exit>(1);> >}> >else> if> (p == 0)> >printf>(>'Child has x = %d '>, ++x);> >else> >printf>(>'Parent has x = %d '>, --x);> }> int> main()> {> >forkexample();> >return> 0;> }>

>

>

出力

Javaでのインスタンス化
Parent has x = 0 Child has x = 2>

または

出力

Child has x = 2 Parent has x = 0>

ここで、2 つのプロセスのデータ/状態は異なるため、1 つのプロセスでのグローバル変数の変更は他の 2 つのプロセスには影響しません。また、親と子が同時に実行されるため、2 つの出力が可能です。

fork() と exec()

fork システムコールは新しいプロセスを作成します。 fork() によって作成される新しいプロセスは、戻り値を除いて現在のプロセスのコピーです。一方、exec() システムコールは、現在のプロセスを新しいプログラムに置き換えます。

C fork() に基づく問題

1. プロセスは次のコードを実行します。

C




for> (i = 0; i fork();>

>

>

作成される子プロセスの総数は次のとおりです。 (ゲート-CS-2008)

(A)n
(B) 2^n – 1
(C) 2^n
(D) 2^(n+1) – 1

解決策については、これを参照してください。

2. 次のコード部分を考えてみましょう。

C




if> (fork() == 0) {> >a = a + 5;> >printf>(>'%d, %d '>, a, &a);> }> else> {> >a = a –5;> >printf>(>'%d, %d '>, a, &a);> }>

>

>

u、v を親プロセスによって出力される値、x、y を子プロセスによって出力される値とする。次のうち正しいのはどれですか? (ゲート-CS-2005)

(A) u = x + 10 および v = y
(B) u = x + 10 および v != y
(C) u + 10 = x および v = y
(D) u + 10 = x および v != y

文字列.部分文字列Java

解決策については、これを参照してください。

3. 以下のプログラムの出力を予測します。

C




#include> #include> int> main()> > >fork();> >fork() && fork()>

>

>

解決策についてはこれを参照してください

関連記事 :

  • fork() と Pipe() をデモする C プログラム
  • C のゾンビおよび孤立プロセス
  • fork() とそれを使用して作成されたメモリ共有白黒プロセス