我正在尝试以下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
分叉进程获取变量内存的副本,并且在分叉时,输出缓冲区尚未被刷新.fork时没有输出写入控制台,只是缓冲了.因此,两个进程都继续使用text1已经在缓冲区中,因此都打印它.
fork克隆当前进程.新流程将在fork通话时"开始" ,而不是在main您预期的开始时.因此,当您第一次打印时有1个进程,那么当您分叉时有两个进程.
由于您fork在打印后进行打印"text1",因此仅打印一次.
在第二个例子中,重复的输出是由于输出缓冲 - printf实际上并没有输出任何东西到屏幕,直到它被刷新或它到达换行符('\n').
因此,第一次调用printf实际上只是将数据写入某个缓冲区,然后将数据复制到第二个进程的地址空间,然后第二次调用printf将刷新缓冲区,并"text1"在两个缓冲区中完成.
| 归档时间: |
|
| 查看次数: |
8832 次 |
| 最近记录: |