IT-Swarm.Net

缓冲与无缓冲 IO

我了解到,默认情况下,程序中的I/O是缓冲的,即它们从临时存储器提供给请求程序。我知道缓冲提高了IO性能(可能通过减少系统调用)。我已经看到了禁用缓冲的例子,例如C中的setvbuf。两种模式之间有什么区别?何时应该使用另一种模式?

65
sud03r

无论何时希望确保在继续之前写入输出,都需要无缓冲输出。一个例子是C运行时库下的标准错误 - 默认情况下,这通常是无缓冲的。由于错误(希望)很少发生,因此您希望立即了解错误。另一方面,标准输出缓冲只是因为它假设将有更多的数据通过它。.

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

此外,不仅系统调用最小化,而且磁盘I/O也是如此。假设一个程序一次读取一个字节的文件。使用无缓冲输入,你会为每个字节输出(相对非常慢)磁盘,即使它可能必须在整个块中读取(磁盘硬件本身可能有缓冲区,但你仍然要去磁盘控制器)这将比内存访问慢。.

通过缓冲,立即将整个块读入缓冲区,然后从(内存中,速度极快)缓冲区传送单个字节。.

请记住,缓冲可以采用多种形式,例如以下示例:

+-------------------+-------------------+
| 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                |
+---------------------------------------+
104
paxdiablo

快速,可靠且价格合理的云托管

注册并在30天内获得$50奖金!

当你已经准备好写入磁盘的大量字节序列时,你想要无缓冲的输出,并希望 避免额外的副本 到中间的第二个缓冲区。.

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

无缓冲输出 没有 与确保数据到达磁盘有关;该功能由flush()提供,适用于缓冲和非缓冲流。无缓冲IO写入不保证数据已到达物理磁盘 - 操作系统文件系统可以无限期地保留数据副本,如果需要,则永远不会将其写入磁盘。调用flush()时,只需将其提交到磁盘。 (请注意,close()将代表您调用flush())。.

28
Aaron