web-dev-qa-db-ja.com

CのFork()関数

以下は、動作中のFork関数の例です。以下も出力です。私の主な質問は、フォークに関するもので、値の変更方法と呼ばれます。したがって、pid1、2、および3は0から始まり、分岐が発生すると変更されます。これは、フォークが発生するたびに値が子にコピーされ、特定の値が親で変更されるためですか?基本的に、フォーク関数で値はどのように変化しますか?

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main() {
    pid_t pid1, pid2, pid3;
    pid1=0, pid2=0, pid3=0;
    pid1= fork(); /* A */
    if(pid1==0){
        pid2=fork(); /* B */
        pid3=fork(); /* C */
    } else {
        pid3=fork(); /* D */
        if(pid3==0) {
            pid2=fork(); /* E */
        }
        if((pid1 == 0)&&(pid2 == 0))
            printf("Level 1\n");
        if(pid1 !=0)
            printf("Level 2\n");
        if(pid2 !=0)
           printf("Level 3\n");
        if(pid3 !=0)
           printf("Level 4\n");
       return 0;
    }
}

次に、これが実行です。

----A----D--------- (pid1!=0, pid2==0(as initialized), pid3!=0, print "Level 2" and "Level 4")
    |    |
    |    +----E---- (pid1!=0, pid2!=0, pid3==0, print "Level 2" and "Level 3")
    |         |
    |         +---- (pid1!=0, pid2==0, pid3==0, print "Level 2")
    |
    +----B----C---- (pid1==0, pid2!=0, pid3!=0, print nothing)
         |    |
         |    +---- (pid1==0, pid2==0, pid3==0, print nothing)
         |
         +----C---- (pid1==0, pid2==0, pid3!=0, print nothing)
              |
              +---- (pid1==0, pid2==0, pid3==0, print nothing)

理想的には、この方法が私にとって理にかなっているので、私はそれをどのように説明したいと思っていますか。 *は、私の主な混乱があるところです。子が、たとえばpid1 = fork();を分岐して、親のすべての値を使用してプロセスを作成しますが、親pid1にlets 1と言うような値を渡しますか?子の意味はpid 1 = 0、pid2 = 0、pid3 = 0、そして親はpid1 = 2、pid2と3は0に等しいでしょうか? enter image description here

18
Plisken

システムコールfork()は、プロセスを作成するために使用されます。引数を取らず、プロセスIDを返します。 fork()の目的は、呼び出し元の子プロセスになる新しいプロセスを作成することです。新しい子プロセスが作成された後、両方のプロセスはfork()システムコールに続く次の命令を実行します。したがって、親と子を区別する必要があります。これは、fork()の戻り値をテストすることで実行できます。

フォークはシステムコールであり、通常のC関数とは考えないでください。 fork()が発生すると独自のアドレス空間を持つ2つの新しいプロセスを効果的に作成します。fork()呼び出しの前に初期化される変数は、両方のアドレス空間に同じ値を格納します。ただし、いずれかのプロセスのアドレス空間内で変更された値は、他のプロセスでは影響を受けません。一方は親で、もう一方は子です。だから、

pid=fork();

後続のコードブロックでpid.Bothプロセスの値を確認すると、コードの全長にわたって実行されます。それで、それらをどのように区別しますか。繰り返しますフォークはシステムコールであり、ここに違いがあります。新しく作成された子プロセスの内部ではpidは0を保存し、親プロセスでは正の値を保存します。pid内の負の値はフォークエラーを示します.

Pidの値をテストして、0に等しいかそれより大きいかを確認するとき、子プロセスまたは親プロセスのどちらにいるのかを効果的に見つけています。

フォークについての詳細を読む

24
Rahul Jha
int a = fork(); 

実行スタックを共有する複製プロセス「clone?」を作成します。親と子の違いは、関数の戻り値です。

0を取得した子が返され、親が新しいpidを取得しました。

スタック変数のアドレスと値がコピーされるたびに。実行は、コード内ですでに到達した時点から継続されます。

forkで、1つの値のみが変更されます-forkからの戻り値。

6
mksteve

最初にfork()のドキュメントへのリンク

http://pubs.opengroup.org/onlinepubs/009695399/functions/fork.html

Pidはカーネルによって提供されます。カーネルが新しいプロセスを作成するたびに、内部pidカウンターを増やし、新しいプロセスにこの新しい一意のpidを割り当て、重複がないことも確認します。 pidが高い数値に達すると、ラップして最初からやり直します。

したがって、fork()から取得するpidがわからないのは、親が一意のpidを保持し、そのforkが子プロセスに新しい一意のpidがあることを確認することだけです。これは、上記のドキュメントに記載されています。

ドキュメントを読み続けると、fork()が子プロセスに対して0を返し、子の新しい一意のpidが親に返されることがわかります。子が自分の新しいpidを知りたい場合は、getpid()を使用してそれを照会する必要があります。

pid_t pid = fork()
if(pid == 0) {
    printf("this is a child: my new unique pid is %d\n", getpid());
} else {
    printf("this is the parent: my pid is %d and I have a child with pid %d \n", getpid(), pid);
}

以下はコードに関するいくつかのインラインコメントです

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main() {
    pid_t pid1, pid2, pid3;
    pid1=0, pid2=0, pid3=0;
    pid1= fork(); /* A */
    if(pid1 == 0){
        /* This is child A */
        pid2=fork(); /* B */
        pid3=fork(); /* C */
    } else {
        /* This is parent A */
        /* Child B and C will never reach this code */
        pid3=fork(); /* D */
        if(pid3==0) {
            /* This is child D fork'ed from parent A */
            pid2=fork(); /* E */
        }
        if((pid1 == 0)&&(pid2 == 0)) {
            /* pid1 will never be 0 here so this is dead code */
            printf("Level 1\n");
        }
        if(pid1 !=0) {
            /* This is always true for both parent and child E */
            printf("Level 2\n");
        }
        if(pid2 !=0) {
           /* This is parent E (same as parent A) */
           printf("Level 3\n");
        }
        if(pid3 !=0) {
           /* This is parent D (same as parent A) */
           printf("Level 4\n");
        }
    }
    return 0;
}
3
leakim