需要知道fork如何工作?

时间:2011-05-15 22:17:05

标签: c process fork

我正在尝试以下C代码:

int main()
{
    printf("text1\n");
    fork();
    printf("text2\n");
    return 0;
}

我期待得到输出,我得到两个“text1”和两个“text2”,如:

text1
text1
text2
text2

但是,相反,我得到了:

text1
text2
text2

只有一个“text1”??? 好吧,如果子进程从fork()执行,那么为什么我得到两个“text1”用于跟随:

int main()  
{  
    printf("text1");  
    fork();  
    printf("text2\n");  
    return 0;  
}  

现在的输出是:

text1text2  
text1text2 

如果子进程在fork之后开始,则输出应为:

text1  
text2  
text2  

7 个答案:

答案 0 :(得分:24)

fork()通过将当前流程中的所有内容复制到新流程中来创建新流程。这通常包括内存中的所有内容以及CPU寄存器的当前值以及一些小的调整。所以实际上,新进程也会获得进程指令指针的副本,因此它会在原始进程继续的同一点(fork()之后的指令)恢复。


为了解决您的更新问题,printf()已缓存。通常,缓冲区在最后遇到换行符'\n'时被刷新。但是,由于您省略了这一点,缓冲区的内容会保留并且不会被刷新。最后,两个进程(原始进程和子进程)都将具有"text1"的输出缓冲区。当它最终被刷新时,你会在两个过程中看到这一点。

实际上,在分叉之前,应始终刷新文件和所有缓冲区(包括stdout),以确保不会发生这种情况。

printf("text1");
fflush(stdout);
fork();

输出应该如下所示(按某种顺序):

text1text2
text2

答案 1 :(得分:7)

forked进程获取变量内存的副本,并且在fork时,输出缓冲区尚未被刷新。 fork时没有输出写入控制台,只是缓冲了。因此,两个进程都继续使用text1已经在缓冲区中,因此都打印它。

答案 2 :(得分:6)

fork克隆当前进程。新流程将在fork来电时“开始”,而不是在main的开头,正如您所期待的那样。因此,当您第一次打印时有1个进程,那么当您分叉时有两个进程。

由于您在打印fork"text1",因此仅打印一次。

在第二个例子中,重复的输出是由于输出缓冲 - printf实际上并没有输出任何东西到屏幕,直到它被刷新或它到达换行符('\n')。

因此,对printf的第一次调用实际上只是将数据写入某个缓冲区,然后将数据复制到第二个进程的地址空间,然后对printf的第二次调用将刷新缓冲区,在两个缓冲区中都有"text1"

答案 3 :(得分:2)

这是因为fork ed进程在fork之后开始,而不是从一开始就开始。 exec从入口点开始处理,并打印出您期望的内容。

答案 4 :(得分:1)

子进程将从fork()的位置开始,因此您将获得正确的输出。

答案 5 :(得分:1)

Problem 1 : the output as
      text1
      text2
      text2

这是因为fork()创建父进程的精确副本(子进程),并且两个进程在系统调用fork()之后立即开始执行。

Problem 2 : the output as
      text1text2 
      text1text2 

这就是缓冲。请参阅此链接并了解fork()基础知识。 http://www.csl.mtu.edu/cs4411.ck/www/NOTES/process/fork/create.html

答案 6 :(得分:0)

来自man 2 fork:fork将0返回到子进程。

value = fork();
if( value == -1 ) {
  printf( "fork failed\n" );
  exit(1);
}
if( value ) {
  printf( "test1\n" );
} else {
  printf( "test2\n" };
}