缓冲与非缓冲IO

我了解到,默认情况下,程序中的I / O被缓冲,即它们从临时存储器被提供给请求程序。 我明白,缓冲提高了IO性能(也许通过减less系统调用)。 我见过禁用缓冲的例子,例如C中的setvbuf 。这两种模式之间的区别是什么?什么时候应该使用另一种模式?

只要希望在继续之前确保输出已被写入,就需要无缓冲的输出。 一个例子是C运行时库下的标准错误 – 默认情况下这通常是无缓冲的。 由于错误(希望)不常发生,所以您希望立即知道这些错误。 另一方面,标准输出简单地缓冲,因为它假定将有更多的数据通过它。

另一个例子是日志库。 如果你的日志消息被保存在你的进程中的缓冲区中,并且你的进程转储了核心,那么很有可能输出永远不会被写入。

另外,这不仅仅是最小化的系统调用,还有磁盘I / O。 假设一个程序一次读取一个字节的文件。 使用无缓冲input时,即使可能必须读取整个数据块(磁盘硬件本身可能有缓冲区,但仍然要到磁盘控制器),每个字节都会出现(相对非常慢)的磁盘这将比内存访问慢)。

通过缓冲,整个块被立即读入缓冲区,然后单个字节从(内存中,难以置信的快速)缓冲区传递给你。

请记住,缓冲可以有多种forms,如下面的例子:

 +-------------------+-------------------+ | Process A | Process B | +-------------------+-------------------+ | C runtime library | C runtime library | C RTL buffers +-------------------+-------------------+ | OS caches | Operating system buffers +---------------------------------------+ | Disk controller hardware cache | Disk hardware buffers +---------------------------------------+ | Disk | +---------------------------------------+ 

当你已经有大量的字节准备好写入磁盘时,你想要无缓冲的输出,并且要避免在中间的第二个缓冲区中多余的拷贝

缓冲输出stream会将写入结果累积到中间缓冲区中,只有在有足够的数据累积(或请求flush())时才将其发送到OS文件系统。 这减less了文件系统调用的次数。 由于文件系统调用在大多数平台上可能比较昂贵(与短的memcpy相比),当执行大量的小写操作时,缓冲输出是一个净赢。 如果您已经有大量缓冲区发送,则无缓冲输出通常会更好 – 复制到中间缓冲区不会进一步减lessOS调用的数量,并引入额外的工作。

无缓冲输出与确保您的数据到达磁盘无关 ; 该function由flush()提供,可用于缓冲和未缓冲的stream。 无缓冲的IO写入不保证数据已经到达物理磁盘 – 操作系统文件系统可以无限期地保存数据的副本,永远不会写入磁盘,如果需要的话。 只需要在调用flush()时将其提交到磁盘。 (请注意,close()将代表您调用flush()。