假设我有以下代码:
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()
命令将始终为上述代码中的 temp.txt 使用文件描述符 1。
此外,是否有可能只将 "Message from A\n"
或 "Message from B\n"
的一部分写入到在 CPU 加载另一个进程并覆盖刚刚写入的部分消息之前与文件描述符 1 关联的缓冲区?
例如
是否有可能父父进程在被子进程中断之前只设法将“消息”写入缓冲区,从而导致 temp.txt 中的以下内容(或类似内容) :
Message from A
from B
Message from B
注意:
上面的代码是我在其中一门课的作业中给我的。我知道打开一个文件然后调用 dup2()
比关闭文件描述符 1 然后再打开文件更好。
最佳答案
如果标准输出是终端,它是行缓冲的。如果它是一个文件,则不需要。这取决于平台/实现。
在您的第二个示例程序中,您没有看到 1000 行,因为您正在使用 _exit
终止子进程。
if (pid == 0)
{
_exit(0);
}
相反,您应该使用 exit。不同之处在于 exit 执行关闭文件和刷新流等操作,然后调用 _exit 执行实际终止。如果您使用常规退出终止子进程(或者只是让它们定期在 main 结束时终止),它们的输出也应该刷新到文件中。
更新:因此,是否_exit是否刷新流是由实现定义的,这可能是 Barmar 在 Mac 和 Linux 上遇到不同结果但退出总是刷新的原因。引用自 _exit 链接:
Whether open streams are closed (without flushing) is implementation-defined
关于c - 关闭标准输出后打开的文件的 POSIX 定义缓冲是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58242460/