0

これは "APUE" の第 8 章 (演習 8.2、第 2 版) の演習です。すべての説明は次のとおりです。

図 7.6 の典型的なメモリ配置を思い出してください。各関数呼び出しに対応するスタック フレームは通常スタックに格納され、vfork の後に子は親のアドレス空間で実行されるため、vfork の呼び出しが main 以外の関数からのもので、子がそれを実行するとどうなるかvfork 後のこの関数からの戻り? これを検証するためのテスト プログラムを作成し、何が起こっているかを図で示します。

私のプログラムでは:

static void f1(void), f2(void);

int main(void) {
    printf("main address: %d\n", main);
    f1();
    f2();
    _exit(0);
}

static void f1(void) {
    printf("f1 address: %d\n", f1);
    pid_t pid;

    if ((pid = vfork()) < 0)
        err_sys("vfork error");
}

static void f2(void) {
    printf("f2 address: %d\n", f2);
    char buf[1000];
    int i;

    for (i = 0; i < sizeof(buf); ++i)
        buf[i] = 0;
}

プログラムを実行すると、出力は次のようになります。

main address: 4196560
f1 address: 4196604
f2 address: 4196663
f1 address: 4196604
[1]    12929 segmentation fault  ./a.out

出力について混乱しています。

  1. print f1 address: xxx、 vfork() を呼び出し、子プロセスが最初に実行されます。
  2. print f2 address: xxx、次に子プロセスが _exit(0) を呼び出します。
  3. f1() からの主な進行状況の戻り時に、f1 のスタック フレームが f2 によって変更されたため、セグメンテーション フォールトが発生する可能性があります。

しかし、なぜf1 address: 41966042 回出力し、なぜ f1 と f2 のアドレスが同じでないのでしょうか?

4

2 に答える 2

0

vfork documentationによると、現在の関数から戻るべきではありません。

vfork() が fork(2) と異なる点は、子プロセスが終了するまで (通常は _exit(2) を呼び出すことによって、または異常な場合は致命的なシグナルの配信後に)、呼び出し元のスレッドが中断されるか、または execve( への呼び出しを行うことです。 2)。その時点まで、子はスタックを含むすべてのメモリを親と共有します。 子は、現在の関数から戻ったり、exit(3) を呼び出したりしてはなりませんが、 _exit(2) を呼び出すことはできます

また、次の点に注意してください。

vfork() は clone(2) の特殊なケースです。親プロセスのページテーブルをコピーせずに新しいプロセスを作成するために使用されます。これは、すぐに execve(2) を発行する子が作成される、パフォーマンスが重要なアプリケーションで役立つ場合があります。

親からページテーブルをコピーしないためvfork、現在の関数から戻らないことは非常に理にかなっています。子が終了すると、親からのスタック フレームが台無しになります。

次の回答も表示できます

于 2016-05-12T20:15:56.483 に答える
0

「f1 の statck フレームが f2 によって変更された」という意味がよくわかりません。

のコードはf2()vfork(). buf初期化されていません。null で終わる文字列が含まれていると信じる理由はありません。したがって、 への呼び出しstrlen()はバッファの最後を読み取る可能性があります。

いずれにせよ、ループで何を期待しているのかわかりません。最初の反復では、iは 0 です。 への呼び出しがstrlen()segfault でない場合、ループ本体は に 0 を格納しbuf[0]ます。したがって、ループの次の反復では、strlen(buf)0 にiなり、1 (0 未満ではない) になるため、ループは終了します。

の 2 番目の出力は、 -ed サブプロセスが終了f1 address: 4196604した後、親プロセスが続行するときです。vfork()親プロセスは続行し、f1()それを出力するのを呼び出します。

印刷する番号は、f1f2それ自体のアドレスです。f1の住所がの住所と同じであると予想するのはなぜf2ですか? そうではないため、異なるアドレスを印刷します。

一方、f1サブプロセスは親のアドレス空間を共有するため、親プロセスとサブプロセスのアドレスは同じです。f1そのため、両方の回で同じアドレスが出力されます。

于 2015-04-05T05:25:31.117 に答える