c - fork函数在C中的位置及其对输出的影响

标签 c linux

我正在学习C语言中的fork函数,并且正在准备过去的考试,遇到一个很有趣的问题。

请参阅下面的代码:

int main(void) {

printf("Hello ");
fork();
printf("Hello ");
fork();
printf("Hello \n");

pause();
return 0;
}

输出结果为

Hello Hello Hello 
Hello Hello Hello 
Hello Hello Hello 
Hello Hello Hello 

如果我将代码更改为

    fork();
    fork();
    printf("Hello ");
    printf("Hello ");
    printf("Hello \n");

输出结果还是一样。 为什么 fork 函数的位置对输出本身没有影响。 fork 是否会等待所有 printf() 完成后再执行?这应该可以解释输出,因为第一次 printf() 会打印出 Hello 的第一行,然后它将被 fork ,并且会再打印 1 行 Hello。然后第二个 fork 将 fork 前 2 行并产生另外 2 行 Hello。

但是,问题只是稍微改变了代码,整个输出就会发生巨大变化。

printf("Hello \n");
fork();
printf("Hello ");
fork();
printf("Hello \n");

这导致输出为

Hello 
Hello Hello 
Hello Hello 
Hello Hello 
Hello Hello

我不明白为什么只添加一个 '\n' 就会导致 5 行输出而不是 4 行。 这次,如果我像以前一样将 fork 函数的位置更改为顶部,则输出会发生变化 看来这次fork函数对printf的第一行没有影响。有人可以向我解释一下 fork 函数到底是如何输出内容的吗?

最佳答案

问题不在于顺序,这无关紧要,因为我们正在处理 fork() 并且您无法保证两个并发线程的并发性。

问题是程序打印了大量的Hello,根据程序的语义,这是不正确的。如果你仔细想想

  • 第一个 printf 仅由父进程执行
  • 第二个printf由父进程和子进程执行
  • 第三个 printf 由父进程、子进程以及父进程和第一个子进程的两个子进程执行

这总共产生了 7 个 printf,而您获得了 12 或 11 个。问题在于,当您使用以下命令调用 fork() 时,输出是按行缓冲的: stdout 缓冲区内有一些东西,然后奇怪的事情发生了。如果您将代码更改为:

#include <unistd.h>

int main(void) {
  printf("(1:%u)\n", getpid());
  fork();
  printf("(2:%u)\n", getpid());
  fork();
  printf("(3:%u)\n", getpid());
  pause();
  return 0;
}

您将获得:

cuboid:Dev jack$ ./a.out 
(1:4307)
(2:4307)
(3:4307)
(2:4308)
(3:4309)
(3:4308)
(3:4310)

这是正确的,因为现在我们在每次调用 printf 时强制刷新(使用 \n),并且 pid 对应于我们之前看到的内容:1 、 2、4 次调用。

如果在代码中调用 fork() 之前强制刷新,例如:

int main(void) {
  printf("1Hello ");
  fflush(stdout);
  fork();
  printf("2Hello ");
  fflush(stdout);
  fork();
  printf("3Hello \n");
  pause();
  return 0;
}

您将获得:

cuboid:Dev jack$ ./a.out 
1Hello 2Hello 3Hello 
2Hello 3Hello 
3Hello 
3Hello 

这会产生相同的正确结果,您可以看到父进程遍历所有 3 行,第一个子进程仅遍历第二行和第三行,而最后两个子进程仅遍历最后一行。

关于c - fork函数在C中的位置及其对输出的影响,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34027414/

相关文章:

linux - 如何使用 docker import 导入多个图像?

c++ - C 和 C++ 上的无效转换错误

c++ - 如果我删除其他进程的共享内存会怎样?

python - 为什么整数可以存储十六进制值但不能以十进制存储相同的值?

linux - 如何一次增加所有 ulimit?

python - 如何使用 python-xlib 读取 X 属性?

Ruby 守护进程不工作

c - gstreamer -plugin intstallation 这个错误是什么意思?

c - 我的 fork() 从不等于 0

c++ - 如何强制 GCC 将常量放入内存而不是生成它们?