fork()の後、子はどこで実行を開始しますか?


22

UNIXプログラミングを学ぼうとしていますが、fork()に関する質問に遭遇しました。fork()は現在実行中のプロセスと同じプロセスを作成することを理解していますが、どこから開始するのですか?たとえば、コードがある場合

int main (int argc, char **argv)
{
    int retval;
    printf ("This is most definitely the parent process\n");
    fflush (stdout);
    retval = fork ();
    printf ("Which process printed this?\n");

    return (EXIT_SUCCESS);
}

出力は次のとおりです。

これは最も確実に親プロセスです
どのプロセスがこれを印刷しましたか?
どのプロセスがこれを印刷しましたか?

私はそれfork()が同じプロセスを作成すると思ったので、最初はそのプログラムでは、fork()呼び出しは永久に再帰的に呼び出されると考えました。から作成された新しいプロセスfork()は、fork()呼び出し後に開始すると思いますか?

次のコードを追加して、親プロセスと子プロセスを区別する場合、

if (child_pid = fork ()) printf ("This is the parent, child pid is %d\n", child_pid);
else printf ("This is the child, pid is %d\n",getpid ());

fork()呼び出しの後、子プロセスはどこで実行を開始しますか?


5
man forkあなたの質問に答えるのに十分だと確信しています、ところで
アレックス

回答:


23

新しいプロセスはfork()呼び出し内で作成され、親と同様にそこから戻ることで開始されます。からの戻り値(に格納したretval)は次のfork()ようになります。

  • 子プロセスでは0
  • 親プロセスの子のPID
  • 障害が発生した場合は、親で-1(当然、子はありません)

テストコードは正しく機能します。fork()in からの戻り値を保存し、0かどうかをチェックするためにchild_pid使用ifします(ただし、エラーはチェックしません)


13

fork()は同じプロセスを作成すると思っていたので、最初はそのプログラムではfork()呼び出しが再帰的に永久に呼び出されると思いました。fork()から作成された新しいプロセスはfork()呼び出しの後に開始すると思いますか?

はい。行に番号を付けましょう:

int main (int argc, char **argv)
{
    int retval;                                               /* 1 */
    printf ("This is most definitely the parent process\n");  /* 2 */
    fflush (stdout);                                          /* 3 */
    retval = fork ();                                         /* 4 */
    printf ("Which process printed this?\n");                 /* 5 */
    return (EXIT_SUCCESS);                                    /* 6 */
}

実行フローは次のとおりです。

caller process     fork()  ...
                          
original program            exec()  2  3  4  5  6
                                               
forked program                                   5  6

...受け取った出力を正確に説明しています。

元のプログラムと分岐したプログラムの動作が異なる可能性があることを知りたい場合は、必ず同じコードを共有するため、Michael Mrozekの回答を参照してください


1は実際には命令ではないことに注意してください。また、元のプログラムとフォークされたプログラムが実際に同時に実行されるわけではないことに注意してください。どちらか一方が他方を譲り渡す/プリエンプトされるまで待つ必要があります。
badp

1
マルチコア/マルチCPUシステムでは、両方のプログラムを実際に同時に実行できます。
-jlliagre

@jilliagreマルチコアシステムは、マルチスレッドに関するものです。複数のCPUを備えたシステムについては、実際にそうなのかどうかはわかりません私はこの分野の専門家ではありません-そして、それはそのようなありそうもないシナリオのように思えます。OSが複数のプロセスを同時に実行できることに同意する場合(それでは並行性をどのように処理しますか?)、元のプログラムがCPUで命令4を実行するまでに、他のCPUは他のプロセスを実行するのに忙しいでしょう。
-badp

特に、手順5でI / Oが発生する基本的なシステムコールがあるため、非常に可能性の高いシナリオと言えます。マルチスレッドとマルチコアを混同しているようです。
jlliagre

8
私はちょうどそれらの対角線の矢印があると言ってコメントすることができます素晴らしいです
JBirch

0

これに対する本当の解決策は

switch (fork()) {
    case -1 :
        fprintf (stderr, "fork failed (%s)\n", strerror(errno));
        break;
    case 0 :  // child process comes here
        break;
    default : // parent process
        break;
}

// all continue here

-1

の直後のコードfork()が子プロセスにコピーされ、親プロセスと子プロセスを混同しないように、これらは同じ(複製された、共有されていない)環境を持つ2つの異なるエンティティです。

出力を確認してください...

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.