【问题标题】:What is the difference between flush() and sync() in regard to fstream buffers?关于 fstream 缓冲区,flush() 和 sync() 有什么区别?
【发布时间】:2012-12-24 11:36:00
【问题描述】:

我正在阅读cplusplus.com tutorial on I/O。最后,它说 fstream 缓冲区与磁盘上的文件同步

明确地,使用操纵器:当某些操纵器用于 流时,会发生显式同步。这些机械手 分别是:flush 和 endl。

显式地,使用成员函数sync():调用 流的成员函数sync(),它不带参数,导致 立即同步。此函数返回一个 int 值,等于 -1 如果流没有关联的缓冲区或发生故障。否则(如果流缓冲区已成功同步)它 返回 0。

除了一些其他隐含的情况(如析构和stream.close())

调用 fstream::flush() 和 fstream::sync() 有什么区别?结束?

在我的代码中,我一直使用flush()。

关于 std::flush() 的文档:

刷新流缓冲区

同步与流关联的缓冲区 到其受控的输出序列。这实际上意味着所有 缓冲区中未写入的字符被写入其受控 尽快输出序列(“flushed”)。

关于 std::streambuf::sync() 的文档:

将输入缓冲区与字符源同步

调用它以将流缓冲区与受控序列(如文件流中的文件)同步。公共成员函数 pubsync 调用这个受保护的成员函数来执行这个动作。

如果这是一个新手问题,请原谅我;我是菜鸟。

【问题讨论】:

    标签: c++ stream buffer fstream ostream


    【解决方案1】:

    basic_ostream::flush 这是一个非虚拟函数,它将未提交的更改写入底层缓冲区。如果出现错误,它会在使用的流对象中设置一个错误标志。这是因为返回值是对流本身的引用,以允许链接。

    basic_filebuf::sync 这是一个 virtual 函数,它将所有待处理的更改写入底层文件并返回一个 错误代码 来表示成功或失败。

    结束 这在应用于ostream 时,会将'\n' 写入流,然后在该流上调用flush

    所以,本质上:flush 是任何流的更通用函数,而 sync 显式绑定到文件。 flush 是非虚拟的,而 sync 是虚拟的。这改变了在继承的情况下如何通过指针(指向基类)使用它们。此外,它们在报告错误的方式上也有所不同。

    【讨论】:

    • 很好的答案。您能否确认/澄清 DWright 和 perreal 关于 flush() 由内核处理和 sync() 由库处理的声明(当内核无法足够快地安排写入时?)?
    • @cjcurrie 写入文件时总是涉及内核,但写入流时不一定涉及内核,因为流可能绑定到完全由库处理的东西(例如字符串流)。
    • 谢谢!我想这就是为什么 John Cormack 在 QuakeCon '11 上持续关注文件分页的原因。
    • 这是错误的,sync() 函数没有写入任何东西。它用于与输入数据同步,而不是与输出同步。
    • 我会说区别在于flush()与输出流有关,而sync()与输出缓冲区有关。 flush()基本调用底层缓冲区的sync(),无论是文件缓冲区还是任何其他缓冲区。 OP询问fstream::flush()fstream::sync()之间的区别,而你描述basic_ostreambasic_filebuf之间的区别,所以我不明白这里发生了什么。
    【解决方案2】:

    syncinput 流的成员,所有未读字符都从缓冲区中清除。 flushoutput 流的成员,缓冲的输出被传递到内核。

    【讨论】:

      【解决方案3】:

      C++ I/O 涉及多个类之间的协作:streambufferlocalelocale::facet -s.

      特别是syncflushstreamstreambuf 中都存在的成员函数,因此请注意您所指的文档,因为它们做不同的事情。

      On streams flush 告诉流告诉缓冲区(注意重定向)将其内容刷新到目的地。这样可以确保没有“挂起的写入”。

      std::endl,当应用于thestream<< 时,只不过是一个

      thestream.put('\n'); thestream.flush();
      

      始终在 streams 上,sync 告诉 stream 告诉 bufferflush 内容(用于输出)并尽可能多地读取(用于输入)以重新填充缓冲区。

      注意,-in buffers-sync 也可以在内部被overflow 调用来处理“buffer full”(用于输出)和“buffer empty”(用于输入)的情况。

      因此我感觉,sync 更像是流中用于缓冲通信和缓冲区实现的“内部”函数(其中它是虚拟的并在不同的缓冲区类型中被覆盖),而 flush 更像是两者之间的接口流和客户端程序。

      endl ... 只是一个捷径。

      【讨论】:

      • On STREAM 和 Always on STREAM 有什么区别?恐怕我不明白你在这里的意思。
      • 我谈到了流、缓冲区和其他东西(语言环境......)。当说“在流上”时,我的意思是“而不是在缓冲区上”。如果您愿意,可以使用“with”而不是“on”。
      【解决方案4】:

      我的理解是这样的:

      flush() 会将数据从库缓冲区中取出到操作系统的写入缓冲区中,并最终导致完全同步(数据被完全写出),但同步完成时间肯定取决于操作系统.

      sync() 将尽可能在给定操作系统中尝试强制实现完全同步 - 但所涉及的操作系统可能会或可能不会促进这一点。

      所以flush() 是:将数据从缓冲区中取出并排队写入。
      sync() 是:如果可能,现在强制将数据明确写出。

      这是我对此的理解,但当我想到它时,我不记得我是如何理解的,所以我也很想听听其他人的意见。

      【讨论】:

        猜你喜欢
        • 2013-02-15
        • 2014-10-10
        • 1970-01-01
        • 1970-01-01
        • 2017-11-24
        • 1970-01-01
        • 1970-01-01
        • 2010-10-19
        • 1970-01-01
        相关资源
        最近更新 更多