2009-09-20 105 views
56

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

回答

90

只要希望确保输出在继续之前被写入,就需要无缓冲的输出。一个例子是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    | 
+---------------------------------------+ 
21

您想无缓冲输出,当你已经准备好向磁盘写入字节的大序列,并希望避免额外复制到中间的第二个缓冲区。

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

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

+0

将调用'flush()'保证它被写入磁盘?我认为只将它传递给磁盘的缓冲区。 – jrdioko 2011-07-14 23:24:58

+2

您需要'O_SYNC'来确保写入。 – moshbear 2011-12-07 00:54:43