web-dev-qa-db-ja.com

C言語でのフォークの動作

今、私はfork()システムコールの働きを理解するのに問題があります。私は次のようなコードを書きます:

_#include<stdio.h>
int main()
{
    int a, b;
    b=fork();

    printf("\n the value of b = %d",b);
}
_

このコードの出力は次のとおりです。

なぜ出力がこんな感じなのかわかりませんか?

その後、コードに1行追加するだけで、出力が完全に異なります。私のコードは次のとおりです。

_int main()
{
    int a, b;
    b=fork();
_

コードを実行すると、出力は次のようになります2389私の名前はマニッシュです

_ the value of b = 0
_

今、私はfork()呼び出しの動作について完全に混乱しています。

私の質問は次のとおりです。

  1. fork()はどのように機能しますか?
  2. コントロールはfork()呼び出しの後にどこに行きますか?
  3. コードの出力に問題がある理由を説明できる人はいますか?
  4. bの出力がさまざまな場所で発生する理由は、最初のコードで_b = 2260_の出力が出力_b = 0_の直前であり、_b = 2389_の値が直前ではないことを意味します。 _b = 0_?

問題に書かれているコードでフォークの働きを説明してください。正しく学ぶことができます。

11
Golu

この関数に名前を付けるためにWordフォークが使用された理由を最初に理解することが役立つ場合があります。 「道路上の分岐点」について聞いたことがありますか?フォークでは、プロセスはパスを分割する必要があります。

まず、fork呼び出しに到達するまで、正常に実行されている単一のプロセスがあります。 forkが呼び出されると、新しいプロセスが作成されます。これは、fork関数の戻り値を除いて、元のプロセスとほぼすべて同じです新しく作成されたプロセスは子プロセスと呼ばれるため、それを生成したプロセスは親プロセスと呼ばれます。

フォークのブランチごとに異なるタスクを実行する必要があるため、子プロセスと親プロセスを区別できる必要があります。そこで、forkの戻り値が出てきます。forkは、子(新しく作成されたプロセス)のプロセスID(pid)を親に返します。子に0を返します。また、forkの実行が失敗した場合、戻り値は-1です。

コードでは、子プロセスと親プロセスを区別しないため、両方のプロセスがfork呼び出しの後に続くコード全体を実行します。

//what the child process looks like after fork is called
int main()
{
    int a, b;
    b=fork(); // <-- current line of execution: 0 is returned to b
    printf("\nmy name is manish\n");
    printf("\n my name is anil\n");
    printf("\n the value of b = %d",b);
}

// what the parent process looks like after fork is called
int main()
{
    int a, b;
    b=fork(); // <-- current line: child process id is returned
    printf("\nmy name is manish\n");
    printf("\n my name is anil\n");
    printf("\n the value of b = %d",b);
}

ご覧のとおり、両方のプロセスのフォークに続くコードは同じであるため、出力が繰り返されます。おそらく、親プロセスにManishを出力させ、子プロセスにAnilを出力させたい場合は、次のようにすることができます。

int main()
{
    pid_t b; // note that the actual return type of fork is 
             // pid_t, though it's probably just an int typedef'd or macro'd

    b = fork();
    if (b == -1) perror("Fork failed");
    else if (b > 0) {
        printf("My name is Manish\n"); // parent process
    else
        printf("My name is Anil\n"); // child process

    printf("The value of b is %d\n", b);
    return 0;
}

最後に、最後にコメントする必要があるのは、コードでは、出力が最初に1つのプロセス全体で実行され、次に他のプロセス全体で実行されたように見えるということです。常にそうであるとは限りません。たとえば、オペレーティングシステムでは、親が「manish」出力を実行してからこのプロセスを待機させ、cpuを子プロセスに渡して「manish」を実行できるようにする場合があります。ただし、子プロセスは続行して「anil」および「b」出力を実行し、子プロセスの実行を完了して、実行を親プロセスに戻すことができます。これで、親は「anil」と「b」自体を出力して実行を終了します。このプログラムを実行した最終出力は、次のようになります。

私の名前はマニッシュです//親によって実行されます
私の名前はanilです//子
 bの値= 0 //子
私の名前はanil// parent 
 b = 2244の値//parent
manish.yadav@ws40-man-lin:〜$

fork のマニュアルページをご覧ください。また、ゾンビを作成しないように、親プロセスによる子プロセスの適切な処理については waitpid を参照してください。

編集:コメントでの質問に答えて、各プロセスを連続して実行する方法についてお答えします。

int main() 
{
     pid_t pid;
     int i;

     for (i=0; i<NUM_PROCESSES; i++)
     {
         pid = fork();
         if (pid == -1) 
         {
             perror("Error forking");
             return -1;
         }
         else if (pid > 0)
         {
             // parent process
             waitpid(-1, NULL, 0); //might want to look at man page for this
                                   // it will wait until the child process is done 
         }
         else 
         {
             // do whatever each process needs to do;
             // then exit()
             doProcess(i);
             exit(0);
         }
     }
     // do anything else the parent process needs to do
     return 0;
}

もちろん、これは最良のコードではありませんが、要点を説明するためだけのものです。ここでの大きなアイデアは、waitpid呼び出しです。これにより、親プロセスは、子プロセスがforkedで終了するまで待機します。子プロセスが完了した後、親はwaitpid呼び出しの後に続行し、forループの別の反復を開始し、別の(次の)プロセスをフォークします。これは、すべての子プロセスが順次実行され、実行が最終的に親に戻るまで続きます。

39
ladaghini
  1. Forkは現在のプロセスのコピーを作成します。
  2. オリジナルとコピーの両方が、fork()が呼び出された時点から実行を継続します。
  3. コードは2回実行されるため、printステートメントも2回評価されます。コピーされたプロセスでは、bの値は0です。元のプロセスでは、bの値はコピーされたプロセスのプロセスIDです。
  4. プロセスが同時に実行を開始すると、オペレーティングシステムによって個別にスケジュールされるため、実際にいつ実行されるかについての保証はありません。
5
Chris Frederick
  1. フォークはOSによって実装されます。基本的に子プロセスを作成し、fork()の後に実行を開始します。

  2. 親プロセスは、ファイルプロセスのプロセスIDを受け取ります。b=fork();bはプロセスIDを持っています。子プロセスはゼロのpidを取得します。

  3. (および4)両方のプロセスを並行して実行することも、タイムスライスすることもできるため、出力は異なります。

あなたはこれをチェックしたいかもしれません: http://en.wikipedia.org/wiki/Fork_(operating_system

3

this から始めたほうがいいです。

ここに説明とコード例があります。

1
Sergei Nikulov