web-dev-qa-db-ja.com

fork()の後、子はどこから実行を始めますか?

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()呼び出しの後、子プロセスはどこで実行を開始しますか?

22
thomas1234

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

  • 子プロセスでは0
  • 親プロセスの子のPID
  • 失敗があった場合は親に-1(当然、子はありません)

テストコードは正しく動作します。 fork()からの戻り値をchild_pidに格納し、ifを使用して0かどうかを確認します(エラーの確認は行いません)

23
Michael Mrozek

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の回答を参照してください。

13
badp

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

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
0
ott--