需要知道fork如何工作?

man*_*avi 6 c fork process

我正在尝试以下C代码:

int main()
{
    printf("text1\n");
    fork();
    printf("text2\n");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我期待获得输出,我得到两个"text1"和两个"text2",如:

text1
text1
text2
text2
Run Code Online (Sandbox Code Playgroud)

但是,相反,我得到:

text1
text2
text2
Run Code Online (Sandbox Code Playgroud)

只有一个"text1"??? 好吧,如果子进程从fork()执行,那么为什么我得到两个"text1"表示以下内容:

int main()  
{  
    printf("text1");  
    fork();  
    printf("text2\n");  
    return 0;  
}  
Run Code Online (Sandbox Code Playgroud)

现在的输出是:

text1text2  
text1text2 
Run Code Online (Sandbox Code Playgroud)

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

text1  
text2  
text2  
Run Code Online (Sandbox Code Playgroud)

Jef*_*ado 24

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


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

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

printf("text1");
fflush(stdout);
fork();
Run Code Online (Sandbox Code Playgroud)

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

text1text2
text2


ang*_*son 7

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

  • @adi,为了获得预期的输出,你应该在第一个printf之后加上`fflush(stdout)` (2认同)

tob*_*ies 6

fork克隆当前进程.新流程将在fork通话时"开始" ,而不是在main您预期的开始时.因此,当您第一次打印时有1个进程,那么当您分叉时有两个进程.

由于您fork在打印后进行打印"text1",因此仅打印一次.

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

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