谁在fork()之后首先执行:父或子?

时间:2011-12-13 19:06:41

标签: c unix fork

我知道它可以是其中之一。但我总是看到孩子在我的UNIX终端上首先执行。此外,为什么父和子并行执行。他们似乎在连续执行。这是因为他们共用同一个终端吗?

5 个答案:

答案 0 :(得分:21)

一般来说,关于执行的相对顺序,没有什么可说的。

现在,让我们考虑一下您的具体问题。如果:

  1. 两个进程都需要花费很多时间才能运行,
  2. 你说的是在另一个任何进展之前,一个运行完成,
  3. 有未使用的CPU周期,
  4. 每次运行应用程序时都会发生这种情况。
  5. 这很可能表明两个进程之间存在一些(可能是非预期的)同步。

答案 1 :(得分:6)

实际上这是预期的行为,即使它当前没有正常运行,这意味着父项可以在孩子之前运行,孩子可以在父母之前运行。

目标是首先运行子进程。

简而言之,它背后的逻辑是,如果孩子先跑,如果孩子正在调用exec,那么写副本(COW)的开销将被消除,因为父母没有任何机会写到地址空间。

答案 2 :(得分:3)

如果你正在调用vfork,那么几乎所有的实现都会定义子进程先运行然后父运行。(直到子进程调用exec)。所以你会注意到vfork的串行执行而不管schedulelar.However当fork只需要创建两个新进程即可。它们可以独立运行。(就像任何其他进程一样)。首先运行哪个进程将严重依赖于调度算法。除了调度算法之外,此时运行的进程数也将决定输出的性质。另外,如果使用标准库i / o函数,它们会以突发形式输出数据(可能不是正确的单词)。这也将在某种程度上决定谁先写。这是一个示例代码(实际上这没有多大意义,但仍然是一个很好的例子,父母和孩子确实同步运行

  #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   

但是如果将fork的数量减少到两个(只有两个进程竞争)那么输出就不那么难看了。它是先执行的父进程。(可能是因为当创建另一个进程时它的当前运行进程)

答案 3 :(得分:1)

实际上没有一个在另一个之前执行。只需父母将fork()然后wait()让孩子完成。如果您使用管道系列命令,它甚至可以分叉几次。

答案 4 :(得分:0)

作为其他答案,您可能不知道,也不应依赖它。

但是从历史上看,在Linux上,父级继续执行,然后是子级。在旧的Linux内核上,它是以相反的方式实现的:快速执行子代,这可能会调用exec。通过这种方式,写存储器上将不会有任何副本(应该在每次写入父对象时都进行复制)。你猜怎么了?所做的更改以微妙的方式破坏了许多工具(并且难以调试),因此将其还原。失去了优化!。

所以不要中继将首先执行哪个进程。

相关问题