私はそれがこれらのいずれかである可能性があることを知っています。しかし、UNIX端末で子が最初に実行されることを常に確認しています。また、親子を並行して実行しないのはなぜですか。それらは連続して実行されているようです。同じ端末を共有しているからですか?
一般に、それらの実行の相対的な順序については何も言えません。
それでは、特定の問題について考えてみましょう。場合:
ほとんどの場合、これは、2つのプロセス間で何らかの(おそらく意図しない)同期が行われていることを示しています。
実際には、それが現在正常に機能していない場合でも、意図した動作です。つまり、親は子の前に実行でき、子は親の前に実行できます。
目標は、最初に子プロセスを実行することです。
要するに、その背後にあるロジックは、子が最初に実行された場合、親がに書き込む機会がないため、子がexec
を呼び出している場合、コピーオンライト(COW)のオーバーヘッドが排除されるということです。アドレス空間。
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つのプロセスのみが競合する)、出力はそれほど醜くなくなります。最初に実行されるのは親です(おそらく、他のプロセスが作成されたときに現在実行中のプロセスであるため)
実際には、一方が他方の前に実行されることはありません。親がfork()
、次にwait()
を実行して、子が完了するだけです。たとえば、パイプでつながれた一連のコマンドを使用すると、数回フォークすることもあります。
他の答えとして、あなたはそれを知らないかもしれません、そしてあなたはそれに頼るべきではありません。
しかし、歴史的にLinuxでは、親は実行を継続し、その後は子になります。古いLinuxカーネルでは、逆の方法で実装されていました。子をすばやく実行します。これにより、おそらくexec
が呼び出されます。このようにして、書き込みメモリにコピーはありません(これは親の書き込みごとに実行する必要があります)。何だと思う?その変更により、多くのツールが微妙に壊れた(そしてデバッグが困難になった)ため、元に戻されました。最適化の喪失!。
したがって、どのプロセスが最初に実行されるかを中継しないでください。