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

发布于 2024-11-07 09:31:05 字数 626 浏览 1 评论 0原文

我正在尝试以下 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  

I am trying the following C code:

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

I was expecting to get the output where i get two "text1" and two "text2", like:

text1
text1
text2
text2

But, i am, instead, getting:

text1
text2
text2

only one "text1"???
Ok, if child process executes from the fork(), then why do i get two "text1" for following:

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

the output now is:

text1text2  
text1text2 

If the child process starts after the fork, output should be:

text1  
text2  
text2  

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

々眼睛长脚气 2024-11-14 09:31:05

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


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

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

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

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

text1text2
text2

fork() creates a new process by copying everything in the current process into the new process. That typically includes everything in memory and the current values of the CPU registers with some minor adjustments. So in effect, the new process gets a copy of the process's instruction pointer as well so it resumes at the same point where the original process would continue (the instruction following the fork()).


To address your update, printf() is buffered. Normally the buffer is flushed when it encounters a newline character at the end, '\n'. However since you have omitted this, the contents of the buffer stays and is not flushed. In the end, both processes (the original and the child) will have the output buffer with "text1" in it. When it eventually gets flushed, you'll see this in both processes.

In practice, you should always flush files and all buffers (that includes stdout) before forking to ensure that this does not happen.

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

The output should look like this (in some order):

text1text2
text2
惜醉颜 2024-11-14 09:31:05

分叉的进程获取变量内存的副本,并且在分叉时输出缓冲区尚未被刷新。当您分叉时,没有任何输出写入控制台,仅进行缓冲。因此,两个进程都以缓冲区中已有的 text1 继续,并打印它。

The forked process gets a copy of the variable memory, and at the time of the fork the output buffer has yet to be flushed. No output has been written to the console when you fork, only buffered up. Both processes thus continues with text1 already in the buffer, and thus both print it.

贪了杯 2024-11-14 09:31:05

fork 克隆当前进程。新进程将在 fork 调用时“启动”,而不是像您预期的那样在 main 开始时“启动”。因此,当您第一次打印时,有 1 个进程,然后当您 fork 时,有两个进程。

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

在第二个示例中,重复的输出是由于输出缓冲造成的 - printf 实际上不会向屏幕输出任何内容,直到它被刷新或遇到换行符 ('\n')。

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

fork clones the current process. The new process will "start" at the fork call, not at the start of main as you seem to expect. Thus when you print the first time there is 1 process, then when you fork there are two.

Since you are forking after printing "text1", it is only printed once.

In the second example the duplicated output is due to output buffering - printf doesn't actually output anything to the screen until it is flushed or it hits a newline ('\n').

Consequently the first call to printf actually just wrote data to a buffer somewhere, the data was then copied into the second process' address space, and then the second call to printf would have flushed the buffer, complete with "text1" in both buffers.

烟燃烟灭 2024-11-14 09:31:05

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

It is because forked process starts after fork, not from very beginning. exec starts process from entry point and will print what you expect.

残疾 2024-11-14 09:31:05

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

The child process will start from the position of the fork(), so you are getting the correct output.

抚笙 2024-11-14 09:31:05
Problem 1 : the output as
      text1
      text2
      text2

This is because fork() create exact copy (child) of parent process and both processes start their execution right after the system call fork().

Problem 2 : the output as
      text1text2 
      text1text2 

This is all about buffering. Refer this link and learn about fork() basics.
http://www.csl.mtu.edu/cs4411.ck/www/NOTES/process/fork/create.html

Problem 1 : the output as
      text1
      text2
      text2

This is because fork() create exact copy (child) of parent process and both processes start their execution right after the system call fork().

Problem 2 : the output as
      text1text2 
      text1text2 

This is all about buffering. Refer this link and learn about fork() basics.
http://www.csl.mtu.edu/cs4411.ck/www/NOTES/process/fork/create.html

淡墨 2024-11-14 09:31:05

来自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" };
}

from man 2 fork: fork returns 0 to the child process.

value = fork();
if( value == -1 ) {
  printf( "fork failed\n" );
  exit(1);
}
if( value ) {
  printf( "test1\n" );
} else {
  printf( "test2\n" };
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文