谁能解释为什么输出
main()
{
printf("hello ");
fork();
printf("hello ");
}
是:
你好你好你好你好
和输出:
main()
{
printf("hello\n");
fork();
printf("hello ");
}
是:
你好
你好你好
\n 对缓冲有什么不同?
谁能解释为什么输出
main()
{
printf("hello ");
fork();
printf("hello ");
}
是:
你好你好你好你好
和输出:
main()
{
printf("hello\n");
fork();
printf("hello ");
}
是:
你好
你好你好
\n 对缓冲有什么不同?
当您fork
复制过程的内存时。这包括stdio
缓冲区,因此如果hello
停留在缓冲区中,它将由两个进程打印。两个进程都继续他们的业务并最终刷新他们的缓冲区,你会看到两次“你好”。
现在在大多数实现中, stdout 是行缓冲的,这意味着 a\n
会触发刷新。因此,当fork
发生这种情况时,缓冲区是空的。防止这种情况的可靠方法是在分叉之前冲洗所有内容。
那么为什么 hello 在第二个输出的第二行出现两次
现在有两个进程(父进程和子进程)执行相同的代码,因此printf
执行了两次。
虽然 cnicutar 的回答描述了常见实现中发生的事情背后的机制,但核心问题是您的程序正在调用未定义的行为。POSIX 规定了为打开文件切换“活动句柄”的规则:
http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_05_01
fork
是文件的新句柄出现的一种情况,除非您已准备好在 之前切换活动句柄fork
,否则在 之后使用它们是未定义的行为fork
:
请注意,在 fork() 之后,存在两个句柄,而之前存在一个句柄。应用程序应确保,如果两个句柄都可以访问,它们都处于另一个可以首先成为活动句柄的状态。应用程序应为 fork() 做好准备,就像它是活动句柄的更改一样。(如果其中一个进程执行的唯一操作是 exec 函数或 _exit()(不是 exit())之一,则永远不会在该进程中访问句柄。)