web-dev-qa-db-ja.com

fork()の後に最初に実行するのは誰ですか:親または子?

私はそれがこれらのいずれかである可能性があることを知っています。しかし、UNIX端末で子が最初に実行されることを常に確認しています。また、親子を並行して実行しないのはなぜですか。それらは連続して実行されているようです。同じ端末を共有しているからですか?

23
Bruce

一般に、それらの実行の相対的な順序については何も言えません。

それでは、特定の問題について考えてみましょう。場合:

  1. どちらのプロセスも実行に重要な時間がかかり、
  2. あなたは、一方がもう一方が進行する前に完了するまで実行すると言っていますany進行し、そして
  3. 未使用のCPUサイクルがあり、
  4. これは、アプリケーションを実行するたびに発生します。

ほとんどの場合、これは、2つのプロセス間で何らかの(おそらく意図しない)同期が行われていることを示しています。

25
NPE

実際には、それが現在正常に機能していない場合でも、意図した動作です。つまり、親は子の前に実行でき、子は親の前に実行できます。

目標は、最初に子プロセスを実行することです。

要するに、その背後にあるロジックは、子が最初に実行された場合、親がに書き込む機会がないため、子がexecを呼び出している場合、コピーオンライト(COW)のオーバーヘッドが排除されるということです。アドレス空間。

6
Milan

Vforkを呼び出す場合、ほとんどすべての実装では、子が最初に実行され、次に親が実行されると定義されています(子がexecを呼び出すまで)。したがって、スケジュールに関係なく、vforkの場合はシリアル実行に気付くでしょう。ただし、forkが単に呼び出される場合2つの新しいプロセスが作成されます。これらは独立して自由に実行できます(他のプロセスと同じように)。どのプロセスが最初に実行されるかは、スケジューリングアルゴリズムに大きく依存します。スケジューリングアルゴリズムに加えて、その時点で実行されているプロセスの数も出力の性質を決定します。さらに、標準ライブラリI/O関数を使用している場合、それらはバーストでデータを出力します(おそらく正しいWordではありません)。それはまた、誰が最初に書くようになるかをある程度決定します。これがサンプルコードです(これは実際にはあまり意味がありませんが、それでも親と子が実際に同期して実行されるという良い例です。

  #include<stdio.h>
  #include<string.h>
  static void charAtTime(char buff[])
{
char *p=buff;
while(*p) {
putc(*p,stdout);
(p++);
}

}
    int main()
{
setbuf(stdout,NULL);   //set output stream to be unbuffered.Now each process will try to throw chars as soon as they are ready
int pid;
char buff[1000];
if((pid=fork())<0)   //First fork
    {
    fprintf(stderr,"Fork error\n");
    }
else if(pid==0)
    {
    strcpy(buff,"i am the child.I love beyblade.I love anime.I love pokemon\n");
   charAtTime(buff);    
  }
   else {
     int pid2=fork();   //secnd fork
     if(pid2==0){
     strcpy(buff,"I am the younger child\n");
         charAtTime(buff);
        }
   else {
int pid3;
pid3=fork();    //third fork
if(pid3==0)
    {
    strcpy(buff,"I am from the 2nd generation\n");
    charAtTime(buff);
    }
     else {
    strcpy(buff,"Our family tree is bit confusing\n");
    charAtTime(buff);
    }
        }

     strcpy(buff,"I am the big daddy of them.I have the right before them\n");
    }

   return 0;
    }

私のシステムでは、次の出力が表示されます

   i am thOeI u ra cmfha mtihley  yoIturne geea rmi  cshf irblodimt
   thceo i2nnlfdd .uIg elnseoivrnea gb
   teiyobnl
   ade.I love anime.I love pokemon   

ただし、フォークの数を2つに減らすと(2つのプロセスのみが競合する)、出力はそれほど醜くなくなります。最初に実行されるのは親です(おそらく、他のプロセスが作成されたときに現在実行中のプロセスであるため)

4
bashrc

実際には、一方が他方の前に実行されることはありません。親がfork()、次にwait()を実行して、子が完了するだけです。たとえば、パイプでつながれた一連のコマンドを使用すると、数回フォークすることもあります。

1
fge

他の答えとして、あなたはそれを知らないかもしれません、そしてあなたはそれに頼るべきではありません。

しかし、歴史的にLinuxでは、親は実行を継続し、その後は子になります。古いLinuxカーネルでは、逆の方法で実装されていました。子をすばやく実行します。これにより、おそらくexecが呼び出されます。このようにして、書き込みメモリにコピーはありません(これは親の書き込みごとに実行する必要があります)。何だと思う?その変更により、多くのツールが微妙に壊れた(そしてデバッグが困難になった)ため、元に戻されました。最適化の喪失!。

したがって、どのプロセスが最初に実行されるかを中継しないでください。

0