Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ms-access/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C fork()的不同输出_C_Fork_System Calls - Fatal编程技术网

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
是行缓冲的情况下触发刷新,只有当您显式将其设置为行缓冲或是终端时才会发生。