web-dev-qa-db-ja.com

フォークシステムコールは実際にどのように機能しますか

フォークシステムコールについて非常に具体的な質問があります。私はこのコードを持っています:

int main (void) 
{
    for (int i = 0; i < 10; i++) {
        pid_t pid = fork ();

        if ( !pid ) {
            printf("CHILD | PID: %d, PPID: %d\n", getpid(), getppid());
            _exit(i + 1);
        }

    }

    for (int i = 0; i < 10; i++) {
        int status;
        waitpid(-1, &status, 0);

        if (WIFEXITED(status)) {
            printf("IM %d AND CHILD WITH EXIT CODE %d TERMINATED\n",
                    getpid(), WEXITSTATUS(status));

        } 
        else {
            printf("ERROR: CHILD NOT EXITED\n");
        }
    }

    return 0;
}

これはこの出力を生成します:

CHILD | PID: 3565, PPID: 3564
CHILD | PID: 3566, PPID: 3564
IM 3564 AND CHILD WITH EXIT CODE 1 TERMINATED
IM 3564 AND CHILD WITH EXIT CODE 2 TERMINATED
CHILD | PID: 3573, PPID: 3564
CHILD | PID: 3567, PPID: 3564
IM 3564 AND CHILD WITH EXIT CODE 9 TERMINATED
IM 3564 AND CHILD WITH EXIT CODE 3 TERMINATED
CHILD | PID: 3568, PPID: 3564
IM 3564 AND CHILD WITH EXIT CODE 4 TERMINATED
CHILD | PID: 3569, PPID: 3564
IM 3564 AND CHILD WITH EXIT CODE 5 TERMINATED
CHILD | PID: 3570, PPID: 3564
IM 3564 AND CHILD WITH EXIT CODE 6 TERMINATED
CHILD | PID: 3571, PPID: 3564
IM 3564 AND CHILD WITH EXIT CODE 7 TERMINATED
CHILD | PID: 3572, PPID: 3564
IM 3564 AND CHILD WITH EXIT CODE 8 TERMINATED
CHILD | PID: 3574, PPID: 3564
IM 3564 AND CHILD WITH EXIT CODE 10 TERMINATED

これは、フォークが実際にどのように機能し、新しいプロセスが実際にどのコードを実行するのか疑問に思います。上記の出力結果を見ると、理解できません。

  1. second for cycleは、first forがすべての反復を終了する前にどのように出力しますか?また、このsecond forは常に親プロセスによって実行されることに気づきました。これにより、firstにいる間は疑問に思います。サイクルの場合、if pid != 0(親プロセスの呼び出しを意味します)サイクルの秒が実行されます(?)
  2. CHILDプロセスがPIDでソートされて印刷されないのはなぜですか?

つまり、最終的に、フォークは実際にどのように機能し、誰が何を実行するのですか?

3
user220019

forkを実行すると、カーネルはフォークプロセスのコピーである新しいプロセスを作成し、両方のプロセスはforkの後で実行を継続します(エラーが発生したかどうか、およびエラーが発生したかどうかを示すリターンコードを使用します)。実行中のコードは親または子です)。この「実行の継続」の部分は、必ずしもすぐに発生するわけではありません。カーネルは新しいプロセスを実行キューに追加するだけで、最終的にスケジュールされて実行されますが、必ずしもすぐに実行されるとは限りません。

これはあなたが尋ねている両方の行動を説明しています:

  • 新しいプロセスは必ずしもすぐにスケジュールされるとは限らないため、子が実行される前に親が実行を継続する可能性があります。
  • 作成順序は実行キューにあまり影響を与えないため、子プロセスが作成された順序で実行される保証はありません。
7
Stephen Kitt