0

私はこのようなコードに出くわしました

int main(void){
  pid_t pid;
  char sharedVariable='P';
  char *ptrSharedVariable=&sharedVariable;
           
  pid = fork()
  if(pid==0) {
     sharedVariable = 'C';
     print("Child Process\n");
     printf("Address is %p\n", ptrSharedVariable);
     printf("char value is %c\n", sharedVariable);
     sleep(5);
  } else {
     sleep(5);
     print("Parent Process\n");
     printf("Address is %p\n", ptrSharedVariable);
     printf("char value is %c\n", sharedVariable);
  }

スタック オーバーフローで学んだことから、親プロセスと子プロセスの char 値が異なることがわかります。子の値は「C」で、親の値は「P」です。また、親と子の両方のアドレスが同じである必要があることもわかります。これは、'sharedVariable'(&sharedVariable) へのアドレスです。

しかし、ここに私の質問があります。

  1. 異なるプロセスに異なる char 値を割り当てるポイントは何ですか? 一つには、各プロセスを pid==0 または >0 で既に識別できるため、このステップは冗長ではありませんか? もう 1 つの理由は、同じ仕事をする 2 つのプロセスを区別する意味がわからないことです。
  2. 親と子のアドレスを同じままにしておくのはなぜですか? それらは同様のタスクを続行すると想定されているため、コードをコピーして貼り付けるだけでよいため、そうすると便利だと思います。迷っているので確認したいです。
  3. fork() を vfork() に置き換えた場合、親の char 値の結果は「C」になりますか?

100 万前もって感謝します。

4

1 に答える 1

0

この質問は何度か回答されています。たとえば、こちら

すでにいくつかの回答で書かれていることを繰り返すかもしれませんが、ここにあなたの3つのポイントのいくつかの精度があります:

  1. sharedVariable変数は親プロセスと子プロセス間で共有されないため、共有したコード内の char 変数 ( ) の命名は混乱を招きます。子のアドレス空間は、親のアドレス空間のコピーです。したがって、ここでは、上記の変数が配置されている独自のスタック (1 つは親のスタック、もう 1 つは子のスタック) で同時に実行されている 2 つのプロセス (父と子) があります。
  2. プロセスのアドレス空間はvirtualです。各プロセスでは、同じ仮想アドレスが表示されますが、適切なコードとデータで実行されます (つまり、異なる物理メモリ位置を「ポイント」します)。最適化はカーネルで行われ、プロセスの 1 つによって変更されるまで可能な限り多くのリソースを共有します (例:コピー オン ライトの原則) が、これはユーザー空間のプログラマーの観点からは透過的です。
  3. を使用するvfork()と、親と子の間でアドレス空間が共有されるため、変数が共有されます。用に作成されているため、コピーはありませんfork()。結果の子プロセスは、コルーチンのようなものです (スタックも共有されるため、スレッドよりも軽量です!)。これが、子が終了するか新しいプログラムを実行するまで、親プロセスが中断される理由です。マニュアルでは、このような操作のリスクについて警告しています。その目標は、プロセスをすぐに実行することです (高速fork()/exec()手順)。GLIBC やその他のライブラリ サービスへの呼び出しが失敗するか、親プロセスで破損が発生する可能性があるため、存続期間の長い子プロセス専用ではありません。vfork()GLIBC からの付加価値のないシステムへの直接呼び出しです。の場合fork()、ユーザー空間ライブラリは、多くの「ハウスキーピング」を行って、ライブラリを親プロセスと子プロセスの両方で使用できるようにします (GLIBC のラッパーfork()pthread_atfork()コールバック)。の場合、子プロセスはexecve()呼び出しvfork()を介して別のプログラムによって直接上書きされることになっているため、この「ハウスキーピング」は行われません。これは、子プロセスがexit() ではなく_exit( )を呼び出す必要がある理由でもあります。これは、子プロセスが親プロセスの登録されたatexit()コールバックを実行し、子プロセスと親プロセスの両方で予期しないクラッシュが発生する可能性があるためです。vfork()
于 2020-11-05T11:15:53.837 に答える