我正在学习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/