C - fdopen 为 STDOUT_FILENO 提供一个流,该流不能与 fflush 一起使用

Rut*_*thy 1 c posix

当我在 Linux 系统上运行以下 C 代码时:

printf("This is sentence 1. ");
write(STDOUT_FILENO, "This is sentence 2.\n", 20);
Run Code Online (Sandbox Code Playgroud)

我以错误的顺序得到输出:

This is sentence 2.
This is sentence 1. 
Run Code Online (Sandbox Code Playgroud)

据我了解,发生这种情况是因为“printf”将数据发送到用户空间中的缓冲区,并且需要一些时间才能到达内核空间,而“write”立即将数据发送到内核空间中的缓存缓冲区。

解决此问题的一种方法是将数据从用户空间缓冲区刷新到内核空间缓冲区,如下所示:

printf("This is sentence 1. ");
fflush(stdout);
write(STDOUT_FILENO, "This is sentence 2.\n", 20);
Run Code Online (Sandbox Code Playgroud)

然后收到正确的输出:

This is sentence 1. This is sentence 2.
Run Code Online (Sandbox Code Playgroud)

我尝试解决此问题的另一种方法是尝试从 STDOUT_FILENO fd 获取标准输出流:

FILE *file = fdopen(STDOUT_FILENO, "w");
printf("This is sentence 1. ");
fflush(file);
write(STDOUT_FILENO, "This is sentence 2.\n", 20);
Run Code Online (Sandbox Code Playgroud)

但是,我得到的输出顺序错误:

This is sentence 2.
This is sentence 1.
Run Code Online (Sandbox Code Playgroud)

为了确保STDOUT_FILENO是代表stdout的fd,我将stdout转换为fd:

int fd = fileno(stdout);
if(fd == STDOUT_FILENO)
    printf("fd == STDOUT_FILENO == %d\n", fd);
Run Code Online (Sandbox Code Playgroud)

并收到了预期的输出:

fd == STDOUT_FILENO == 1
Run Code Online (Sandbox Code Playgroud)

那么,问题是为什么当将 STDOUT_FILENO 转换为与 stdout 等效的流时,“fflush”函数不起作用?我使用“fdopen”的方式有问题吗?

Ste*_*mit 5

buffer是stdio流的一个属性,即FILE结构体。 printf始终打印到stdout,因此这是stdout您需要调用的流fflush。当你写下

FILE *file = fdopen(STDOUT_FILENO, "w");`
Run Code Online (Sandbox Code Playgroud)

,这给了你第二个完全独立的FILE流,有自己的缓冲区。但是您不会向该流打印任何内容,因此落在该流fflush上不会产生任何效果,同时,您打印到的文本stdout仍然不会刷新。

如果您在 上有缓冲输出,则必须调用stdout它。(或者,在使用 打印的字符串末尾添加 a ,因为通常是行缓冲的,至少如果它要发送到终端的话。)stdoutfflush\nprintfstdout