代码之家  ›  专栏  ›  技术社区  ›  sud03r

缓冲与非缓冲IO

  •  62
  • sud03r  · 技术社区  · 15 年前

    我了解到,默认情况下,程序中的I/O被缓冲,即从临时存储器向请求程序提供服务。 我知道缓冲可以提高IO性能(可能通过减少系统调用)。我见过禁用缓冲的例子,比如 setvbuf 在C语言中,这两种模式有什么区别?一种模式应在何时使用?

    2 回复  |  直到 6 年前
        1
  •  97
  •   paxdiablo    15 年前

    在继续之前,只要想确保输出已写入,就需要无缓冲输出。一个例子是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                |
    +---------------------------------------+
    
        2
  •  25
  •   Aaron    6 年前

    当您已经准备好写入磁盘的大量字节序列时,您需要无缓冲的输出,并且希望 避免额外复制 进入中间的第二个缓冲区。

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

    无缓冲输出具有 没有什么 确保数据到达磁盘;该功能由 刷新() 并在缓冲流和未缓冲流上工作。无缓冲IO写入不能保证数据已到达物理磁盘--OS文件系统可以无限期地保留数据的副本,如果需要,永远不要将其写入磁盘。只有在调用时才需要将其提交到磁盘 刷新() . (注意 close() 将呼叫 刷新() 代表你)。