C 需要知道fork是如何工作的吗?
我正在尝试以下C代码:C 需要知道fork是如何工作的吗?,c,process,fork,C,Process,Fork,我正在尝试以下C代码: int main() { printf("text1\n"); fork(); printf("text2\n"); return 0; } 我希望得到两个“text1”和两个“text2”的输出,比如: 但是,我却得到了: text1 text2 text2 只有一个“文本1”??? 好的,如果子进程是从fork()执行的,那么为什么我会得到以下两个“text1”: int main() { printf("text1
int main()
{
printf("text1\n");
fork();
printf("text2\n");
return 0;
}
我希望得到两个“text1”和两个“text2”的输出,比如:
但是,我却得到了:
text1
text2
text2
只有一个“文本1”???
好的,如果子进程是从fork()执行的,那么为什么我会得到以下两个“text1”:
int main()
{
printf("text1");
fork();
printf("text2\n");
return 0;
}
现在的输出是:
text1text2
text1text2
如果子进程在fork之后启动,则输出应为:
text1
text2
text2
这是因为
fork
ed过程在fork
之后开始,而不是从一开始exec
从入口点启动流程,并将打印您期望的内容。这是因为fork
ed流程在fork
之后启动,而不是从一开始exec
从入口点启动流程,并将打印您期望的内容。fork
克隆当前流程。新进程将在fork
调用处“启动”,而不是在main
的开始处,正如您所期望的那样。因此,当您第一次打印时,有一个进程,而当您分叉时,有两个进程
由于您在打印“text1”
后正在使用fork
,因此只打印一次
在第二个示例中,重复的输出是由于输出缓冲造成的-printf实际上不会向屏幕输出任何内容,直到刷新或碰到换行符('\n'
)
因此,对
printf
的第一次调用实际上只是将数据写入某个缓冲区,然后将数据复制到第二个进程的地址空间,然后对printf
的第二次调用将刷新缓冲区,并完成“text1”
在两个缓冲区中。fork克隆当前进程。新进程将在fork
调用处“启动”,而不是在main
的开始处,正如您所期望的那样。因此,当您第一次打印时,有一个进程,而当您分叉时,有两个进程
由于您在打印“text1”
后正在使用fork
,因此只打印一次
在第二个示例中,重复的输出是由于输出缓冲造成的-printf实际上不会向屏幕输出任何内容,直到刷新或碰到换行符('\n'
)
因此,对printf
的第一次调用实际上只是将数据写入某个缓冲区,然后将数据复制到第二个进程的地址空间,然后对printf
的第二次调用将刷新缓冲区,并在两个缓冲区中完成“text1”
。fork()
通过将当前流程中的所有内容复制到新流程中来创建新流程。这通常包括内存中的所有内容和CPU寄存器的当前值,只需稍作调整。因此,实际上,新进程也会获得进程指令指针的副本,因此它会在原始进程将继续的同一点(位于fork()
之后的指令)恢复
为了解决更新问题,缓冲了
printf()
。通常,当缓冲区在结尾遇到换行符时,'\n'
会刷新缓冲区。但是,由于您忽略了这一点,缓冲区的内容将保持不变,并且不会刷新。最后,两个进程(原始进程和子进程)都将有一个输出缓冲区,其中包含“text1”
。当它最终被刷新时,您将在两个进程中看到这一点
实际上,在分叉之前,您应该始终刷新文件和所有缓冲区(包括stdout
),以确保不会发生这种情况
printf("text1");
fflush(stdout);
fork();
输出应如下所示(按一定顺序):
文本1文本2
文本2
fork()
通过将当前进程中的所有内容复制到新进程中来创建新进程。这通常包括内存中的所有内容和CPU寄存器的当前值,只需稍作调整。因此,实际上,新进程也会获得进程指令指针的副本,因此它会在原始进程将继续的同一点(位于fork()
之后的指令)恢复
为了解决更新问题,缓冲了
printf()
。通常,当缓冲区在结尾遇到换行符时,'\n'
会刷新缓冲区。但是,由于您忽略了这一点,缓冲区的内容将保持不变,并且不会刷新。最后,两个进程(原始进程和子进程)都将有一个输出缓冲区,其中包含“text1”
。当它最终被刷新时,您将在两个进程中看到这一点
实际上,在分叉之前,您应该始终刷新文件和所有缓冲区(包括stdout
),以确保不会发生这种情况
printf("text1");
fflush(stdout);
fork();
输出应如下所示(按一定顺序):
文本1文本2
文本2
子进程将从fork()的位置开始,因此您将获得正确的输出。子进程将从fork()的位置开始,因此您将获得正确的输出。分叉进程将获得变量内存的副本,在分叉时,输出缓冲区尚未刷新。fork时没有向控制台写入输出,只是缓冲了。因此,这两个进程都将继续使用缓冲区中已经存在的text1,并将其打印出来。分叉进程将获得变量内存的副本,在分叉时,输出缓冲区尚未刷新。fork时没有向控制台写入输出,只是缓冲了。因此,这两个进程都将继续使用缓冲区中已经存在的text1,并将其打印出来。from
man2 fork
:fork将0返回给子进程
value = fork();
if( value == -1 ) {
printf( "fork failed\n" );
exit(1);
}
if( value ) {
printf( "test1\n" );
} else {
printf( "test2\n" };
}
from
man2 fork
:fork将0返回给子进程
value = fork();
if( value == -1 ) {
printf( "fork failed\n" );
exit(1);
}
if( value ) {
printf( "test1\n" );
} else {
printf( "test2\n" };
}
问题1:输出为
文本1
文本2
text2这是因为fork()创建父进程的精确副本(子进程),两个进程在系统调用fork()之后立即开始执行 问题2:输出为 文本1文本2 文本1 Problem 1 : the output as text1 text2 text2 Problem 2 : the output as text1text2 text1text2