5

次のコードスニペットについて考えてみます。

if (fork() == 0)
{
     a = a + 5;
     printf("%d, %d \n", a, &a);
}
else
{
     a = a - 5;
     printf ("%d, %d \n", a,& a);
}

AFAIK、fork()が作成されると、親の仮想アドレススペースが子にコピーされ、子と親のどちらかが変更を試みるまで、子と親の両方が同じ物理ページを共有します。子と親の1つが変数を変更すると、親の物理ページが子の別のページにコピーされ、物理ページは非公開のままになります。したがって、ここで「a」の値は子と親で異なります。ただし、子と親の「a」のアドレスについては、出力は同じです。物理的なページが異なっていても、アドレスが同じままである理由がわかりません。

4

2 に答える 2

7

のアドレスはa、実際の物理アドレスではありません。

仮想アドレスです。
ハードウェア/OS レイヤーは、仮想アドレスを物理アドレスに (アプリケーションには見えないように) マップします。

したがって、アドレスが同じnumberであっても、RAM チップの同じ物理メモリにマップされません。

PS。printf() を使用してアドレス (つまりポインター) を出力する場合は、"%p" を使用するのが最適です。

于 2012-05-23T08:33:13.930 に答える
3

応答はほとんどあなたの質問にあります:の物理ページはa変更後にコピーされます(したがって、親プロセスと同じではありません)aが、仮想アドレス(プログラムによって表示されるもの&a)は変更されません。

実際a、新しい値を割り当てるときにの仮想アドレスを変更するのは非常に厄介です。a以前に:へのポインタを格納していた場合はどうなるか考えてみてください。

 int *p = &a;
 a = a - 5;
 printf("%d", *p)

a2行目以降のpは、プログラマーが予期しない動作を指していません。

物理ページにコピーオンライトを使用することは、プログラムの動作に関係のないOSの最適化です。フォークすると、アドレス空間全体がコピーされると見なすことができます。

于 2012-05-23T08:47:05.820 に答える