为什么printf在调用后不刷新,除非格式字符串中有换行符?这是POSIX行为吗?如何让printf每次都立即刷新?


当前回答

注意:Microsoft运行时库不支持行缓冲,因此printf(“将立即打印到终端”):

https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/setvbuf

其他回答

默认情况下,stdout是行缓冲,stderr是无缓冲,文件是完全缓冲。

这样做可能是为了提高效率,也因为如果有多个程序写入一个TTY,这样就不会让一行上的字符相互交错。所以如果程序A和B输出,你通常会得到:

program A output
program B output
program B output
program A output
program B output

这太糟糕了,但总比

proprogrgraam m AB  ououtputputt
prproogrgram amB A  ououtputtput
program B output

请注意,它甚至不保证在换行上刷新,因此如果刷新对您很重要,则应该显式刷新。

立即刷新调用fflush(stdout)或fflush(NULL) (NULL表示刷新所有内容)。

一般有2级缓冲-

1. 内核缓冲区缓存(使读/写更快)

2. I/O库中的缓冲(减少no。系统调用)

让我们以fprintf和write()为例。

When you call fprintf(), it doesn't wirte directly to the file. It first goes to stdio buffer in the program's memory. From there it is written to the kernel buffer cache by using write system call. So one way to skip I/O buffer is directly using write(). Other ways are by using setbuff(stream,NULL). This sets the buffering mode to no buffering and data is directly written to kernel buffer. To forcefully make the data to be shifted to kernel buffer, we can use "\n", which in case of default buffering mode of 'line buffering', will flush I/O buffer. Or we can use fflush(FILE *stream).

现在我们在内核缓冲区中。内核(/OS)希望最小化磁盘访问时间,因此它只读取/写入磁盘块。因此,当发出read()时(这是一个系统调用,可以直接或通过fscanf()调用),内核从磁盘读取磁盘块并将其存储在缓冲区中。之后,数据从这里复制到用户空间。

类似地,从I/O缓冲区接收到的fprintf()数据由内核写入磁盘。这使得read() write()更快。

现在要强制内核启动write(),之后的数据传输由硬件控制器控制,也有一些方法。我们可以在写调用期间使用O_SYNC或类似的标志。或者我们可以使用其他函数,如fsync(),fdatasync(),sync(),让内核在内核缓冲区中有数据时立即启动写操作。

Stdout是缓冲的,因此只在打印换行符后输出。

要获得立即输出,可以:

打印到标准错误。 使stdout无缓冲。