使用 fflush(stdout) 和不使用它有什么不同
what is the different of using fflush(stdout) and not using it
#include <stdio.h>
int main()
{
printf("Hello");
fflush(stdout);
return 0;
}
#include <stdio.h>
int main()
{
printf("Hello");
return 0;
}
我想了解 fflush(stdout) 的用法以及上面两个程序之间的区别是什么?
当 stdout
指向 tty 时,它默认为 line-buffered。这意味着输出在 计算机内部 内缓冲,直到接收到整行(并输出)。
您的程序没有向计算机内部发送整行。
在使用 fflush()
的情况下,您是在告诉 计算机内部 将缓冲区中的当前数据发送到设备;如果没有 fflush()
,您将依赖 计算机内部结构 在程序终止时为您执行此操作。
计算机内部结构 我的意思是 C 库、操作系统、硬件接口、各种接口之间的(自动)缓冲区的组合,...
在现代 OS 上的普通 C 程序 运行 中,文件访问被缓冲两次(或更多,当您计算像驱动器中的缓冲区这样的缓冲区时)。一个缓冲区在FILE
结构中实现,另一个在内核中实现。
通常,FILE
结构会将内容缓冲在程序内部的缓冲区中。当您向缓冲文件写入内容时,内容会保留在 运行 程序内部的缓冲区中。当缓冲区已满时,它被写入 OS,当缓冲模式为行缓冲时,在一行的末尾。此数据通过系统调用写入 OS,例如 write()
。
缓冲区在那里是因为系统调用需要从用户程序到内核的上下文切换,这是相对昂贵的(慢),缓冲区在这里是为了减少系统调用的次数。您也可以在没有 stdio
函数的情况下直接使用程序中的系统调用,但是,此函数的可移植性较差且处理起来更复杂。
fflush(stdout)
检查缓冲区中是否有任何应写入的数据,如果有,则使用底层系统调用将数据写入 OS.
当系统调用returns时,数据在你的内核中。但现代操作系统也会缓冲这些数据。这用于减少磁盘写入次数,减少延迟和其他事情。此缓冲区完全独立于程序中的 FILE
缓冲区。
请注意,这并不适用于所有系统。例如,微控制器环境可能会提供一些直接写入 UART 的 stdio.h
函数,没有任何缓冲区,既不在 FILE
内部,也不在任何(可能不存在的)OS.
中
要查看 fflush()
对 运行 程序的作用,请比较以下程序:
int main(void)
{
fputs("s",stdout);
fputs("e",stderr);
}
和
int main(void)
{
fputs("s",stdout);
fflush(stdout);
fputs("e",stderr);
}
在Linux上,stderr
默认不缓冲,所以fputs("e",stderr);
会立即打印数据。另一方面,fputs("s",stdout);
默认情况下在 Linux 上进行行缓冲,因此不会立即打印数据。这导致第一个程序输出 es
而不是 se
,但第二个程序输出 se
.
您可以使用 setvbuf()
更改缓冲模式
#include <stdio.h>
int main()
{
printf("Hello");
fflush(stdout);
return 0;
}
#include <stdio.h>
int main()
{
printf("Hello");
return 0;
}
我想了解 fflush(stdout) 的用法以及上面两个程序之间的区别是什么?
当 stdout
指向 tty 时,它默认为 line-buffered。这意味着输出在 计算机内部 内缓冲,直到接收到整行(并输出)。
您的程序没有向计算机内部发送整行。
在使用 fflush()
的情况下,您是在告诉 计算机内部 将缓冲区中的当前数据发送到设备;如果没有 fflush()
,您将依赖 计算机内部结构 在程序终止时为您执行此操作。
计算机内部结构 我的意思是 C 库、操作系统、硬件接口、各种接口之间的(自动)缓冲区的组合,...
在现代 OS 上的普通 C 程序 运行 中,文件访问被缓冲两次(或更多,当您计算像驱动器中的缓冲区这样的缓冲区时)。一个缓冲区在FILE
结构中实现,另一个在内核中实现。
通常,FILE
结构会将内容缓冲在程序内部的缓冲区中。当您向缓冲文件写入内容时,内容会保留在 运行 程序内部的缓冲区中。当缓冲区已满时,它被写入 OS,当缓冲模式为行缓冲时,在一行的末尾。此数据通过系统调用写入 OS,例如 write()
。
缓冲区在那里是因为系统调用需要从用户程序到内核的上下文切换,这是相对昂贵的(慢),缓冲区在这里是为了减少系统调用的次数。您也可以在没有 stdio
函数的情况下直接使用程序中的系统调用,但是,此函数的可移植性较差且处理起来更复杂。
fflush(stdout)
检查缓冲区中是否有任何应写入的数据,如果有,则使用底层系统调用将数据写入 OS.
当系统调用returns时,数据在你的内核中。但现代操作系统也会缓冲这些数据。这用于减少磁盘写入次数,减少延迟和其他事情。此缓冲区完全独立于程序中的 FILE
缓冲区。
请注意,这并不适用于所有系统。例如,微控制器环境可能会提供一些直接写入 UART 的 stdio.h
函数,没有任何缓冲区,既不在 FILE
内部,也不在任何(可能不存在的)OS.
要查看 fflush()
对 运行 程序的作用,请比较以下程序:
int main(void)
{
fputs("s",stdout);
fputs("e",stderr);
}
和
int main(void)
{
fputs("s",stdout);
fflush(stdout);
fputs("e",stderr);
}
在Linux上,stderr
默认不缓冲,所以fputs("e",stderr);
会立即打印数据。另一方面,fputs("s",stdout);
默认情况下在 Linux 上进行行缓冲,因此不会立即打印数据。这导致第一个程序输出 es
而不是 se
,但第二个程序输出 se
.
您可以使用 setvbuf()