关闭 stdout 后打开的文件的 POSIX 定义的缓冲是什么?

What is the POSIX-defined buffering on a file opened after closing stdout?

假设我有以下代码:

close(1);
int fd = open("temp.txt", O_WRONLY | O_CREAT);
if (fork() == 0)
    printf("Message from A\n");
printf("Message from B\n");

我知道 stdout 是行缓冲的,而且我注意到,至少在我的系统上,它可以正常工作。

temp.txt的内容是:

Message from B
Message from A
Message from B

但是,POSIX 为上述代码定义的行为是什么?是否为文件描述符 1 保留了行缓冲(即使在 close() 之后)?它是未定义的吗?还有别的吗?我假设 open() 命令将始终使用文件描述符 1 作为上述代码中的 temp.txt

此外,在 CPU 加载另一个之前,是否有可能只将 "Message from A\n""Message from B\n" 的一部分写入与文件描述符 1 关联的缓冲区处理并覆盖刚刚写入的部分消息?

例如

有没有可能是父进程在被子进程打断前只写了"Message"到buffer,导致temp.txt[中出现如下内容=45=](或类似的东西):

Message from A
 from B
Message from B


注意:

上面的代码是我在 类 的一项作业中给我的。我明白打开一个文件然后调用 dup2(),而不是关闭文件描述符 1,然后再打开文件。

POSIX没有指定C的缓冲,是C标准指定的。

标准输入和输出流的默认缓冲是在程序启动时确定的。更改与流关联的 FD 对此没有影响。如果 stdout 最初与终端相关联,它将是行缓冲的,并且在 FD 1 上打开文件不会改变这一点,因此在写入文件时它仍然是行缓冲的。

如果标准输出是终端,它是行缓冲的。如果它是一个文件,则不需要。这取决于 platform/implementation.
在您的第二个示例程序中,您没有看到 1000 行,因为您正在使用 _exit 终止子进程。

if (pid == 0)
{

    _exit(0);
}

相反,您应该使用 exit。不同之处在于 exit 执行关闭文件和刷新流等操作,然后调用 _exit 执行实际终止。如果您使用常规退出终止子进程(或者只是让它们定期在 main 结束时终止),它们的输出也应该刷新到文件中。

更新:因此,_exit 是否刷新流是实现定义的,这可能是 Barmar 在 Mac 和 Linux 中遇到不同结果但退出总是刷新的原因。引用自 _exit link:

Whether open streams are closed (without flushing) is implementation-defined