C 需要知道fork是如何工作的吗?

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

我正在尝试以下C代码:

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