C fork()的不同输出
有人能解释为什么C fork()的不同输出,c,fork,system-calls,C,Fork,System Calls,有人能解释为什么 main() { printf("hello "); fork(); printf("hello "); } 是: 你好你好你好 以及以下各项的产出: main() { printf("hello\n"); fork(); printf("hello "); } 是: 你好 你好你好 缓冲区的w.r.t有什么区别?当您fork复制进程的内存时。这包括stdio缓冲区,
main()
{
printf("hello ");
fork();
printf("hello ");
}
是:
你好你好你好
以及以下各项的产出:
main()
{
printf("hello\n");
fork();
printf("hello ");
}
是:
你好你好你好
缓冲区的w.r.t有什么区别?当您
fork
复制进程的内存时。这包括stdio
缓冲区,因此,如果hello
停留在缓冲区中,它将由两个进程打印。这两个过程都会继续处理业务,并最终刷新缓冲区,您会看到两次“hello”
现在在大多数实现中,标准输出是行缓冲的,这意味着\n
触发刷新。因此,当分叉发生时,缓冲区是空的。防止这种情况的可靠方法是在分叉之前冲洗所有东西
编辑
那么,为什么hello会在第二行的第二行出现两次呢
输出
现在有两个进程(父进程和子进程)执行相同的代码,因此printf
执行两次。虽然cnicutar的回答描述了常见实现中发生的事情背后的机制,但核心问题是您的程序调用了未定义的行为。POSIX为打开的文件设置了切换“活动句柄”的规则:
fork
是一种存在文件新句柄的情况,除非您在fork
之前准备切换活动句柄,否则在fork
之后使用这两个句柄是未定义的行为:
请注意,在fork()之后,存在两个句柄,其中一个句柄以前存在。应用程序应确保,如果两个句柄都可以访问,则它们都处于另一个可以首先成为活动句柄的状态。应用程序应准备fork(),就像它是活动句柄的更改一样。(如果其中一个进程执行的唯一操作是一个exec函数或_exit()(非exit()),则该进程中永远不会访问句柄。)
那么,为什么hello在第二个输出的第二行中出现两次呢?换句话说,缓冲区必须是空的——也就是说,在分叉之前,句柄需要刷新,或者它是空的。在第二个示例中,\n
触发刷新…但在第一个示例中没有这样做。\n
仅在stdout
是行缓冲的情况下触发刷新,只有当您显式将其设置为行缓冲或是终端时才会发生。