c - 关闭标准输出后打开的文件的 POSIX 定义缓冲是什么?

标签 c posix file-descriptor multiprocess

假设我有以下代码:

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/

相关文章:

c++ - 从 shm_open() + mmap() 更改共享内存的可见性

c++ - 当 CPU 负载过大时 pthread_cond_timedwait 超时

c++ - 为什么我需要从主线程使用 `pthread_exit()`,而它不是由 `pthread_create` 创建的?

c - 声明内联函数后,什么会再次导致多重定义错误?

c++ - 带着面具搜索

c++ - 关闭 GTK 窗口

c - 请告诉我这段代码的答案?

捕获从 netcat 发送的 EOF

c++ - SSL 套接字释放和关闭

c - 默认写入行为-O_TRUNC或O_APPEND?