在现代操作系统上运行的普通 C 程序中,文件访问会被缓冲两次(或者当您计算驱动器中的缓冲区等缓冲区时会缓冲更多次)。一个缓冲区实现在FILE
结构体,另一个是在内核中实现的。
通常,FILE
结构缓冲程序内部缓冲区中的内容。当您向缓冲文件写入内容时,内容将保留在正在运行的程序内部的缓冲区中。当缓冲区已满时,以及当缓冲模式为行缓冲时,在行末尾将其写入操作系统。该数据通过系统调用写入操作系统,例如write()
。
缓冲区之所以存在,是因为系统调用需要从用户程序到内核的上下文切换,这是相对昂贵的(慢),缓冲区在这里是为了减少系统调用的数量。您还可以直接使用程序中的系统调用,而无需stdio
函数,但是,此函数的可移植性较差并且处理起来更复杂。
Afflush(stdout)
检查缓冲区中是否有任何应写入的数据,如果有,则使用底层系统调用将数据写入操作系统。
当系统调用返回时,数据就在您的内核中。但现代操作系统也会缓冲这些数据。这用于减少磁盘写入次数、减少延迟等。该缓冲区完全独立于FILE
程序内的缓冲区。
请注意,这并不适用于所有系统。例如,微控制器环境可能提供一些stdio.h
直接写入 UART 的函数,没有任何缓冲区,内部也没有FILE
也没有任何(可能不存在)操作系统。
看什么fflush()
对正在运行的程序做的事情,比较这个程序:
int main(void)
{
fputs("s",stdout);
fputs("e",stderr);
}
and
int main(void)
{
fputs("s",stdout);
fflush(stdout);
fputs("e",stderr);
}
在 Linux 上,stderr
默认情况下不缓冲,所以fputs("e",stderr);
将立即打印数据。另一方面,fputs("s",stdout);
Linux 上默认是行缓冲的,因此不会立即打印数据。这导致第一个程序输出es
并不是se
,但第二个输出se
.
您可以使用以下命令更改缓冲模式setvbuf()