【问题标题】:How to know when a buffer flush is needed?如何知道何时需要刷新缓冲区?
【发布时间】:2018-10-02 03:55:12
【问题描述】:

考虑两个刷新缓冲区的函数:

  1. fflush()
  2. sync()

我如何知道何时需要呼叫其中任何一个?

我知道将'\n' 添加到printf() 将刷新输出缓冲区,但如果字符串不包含这样的字符,我什么时候可以跳过这个调用,什么时候不可以(多线程系统?)?

sync 也是如此。我有一个将文件保存到文件系统中的函数(保存是通过一系列系统调用完成的),似乎没有调用sync 文件在特定情况下不会保存

不幸的是,我目前没有关于该案例的所有详细信息 [我所知道的是文件已保存,然后立即断电(不知道确切的时间) 并且文件在重新启动后不存在]。在我运行的所有测试中,文件均已正确保存。

那么,我怎么知道系统什么时候会刷新文件数据/元数据缓冲区,什么时候不会,我需要显式调用sync()

引用 man (未指定何时需要显式调用)

sync, syncfs - commit buffer cache to disk
sync() causes all buffered modifications to file metadata and data to be written to the underlying file systems.

fflush - flush a stream
For  output  streams,  fflush() forces a write of all user-space buffered data for the given output or update stream via the stream's underlying write function.  For input streams, fflush() discards any buffered data that has been fetched from the underlying file, but has not been consumed by the application.  The open status  of the stream is unaffected.

附带问题:

The 1st comment on this answer 展示了一种使用setbuf(stdout, NULL); 禁用stdout 缓冲的方法。 sync 有类似的东西吗(使用什么缓冲区?)?

【问题讨论】:

  • "将 '\n' 添加到 printf() 将刷新输出缓冲区" --> 通常 - 也许:What are the rules of automatic flushing stdout buffer in C?。然而,对于 Linux,它可能是这样指定的。
  • 我认为这个问题没有一般的答案。刷新和同步只是 C 库提供的功能。当您详细说明程序的算法时,您将知道何时使用它。
  • CIsForCookies 你有我的 UV,但是当它刷新时需要 1)就在用户输入之前 2)就在打印错误消息之前,3)无论何时。跨度>

标签: c linux buffer fflush


【解决方案1】:

sync()

您很少需要致电sync()。当你这样做时,你有一些至关重要的东西必须尽快记录在磁盘上。但是,sync() 将在计划写入内核内存中的缓冲区后返回,而不是在它们被写入之后,因此您不会知道它们实际上已被写入 - 所以它并不完全可靠。如果您需要对文件的写入进行更多控制,请查看open()O_SYNCO_DSYNCO_RSYNC 标志。如果您使用文件流而不是文件描述符,您可能必须使用fcntl()fileno() 来设置这些标志。

两个警告:

  1. sync() 不会将缓冲区从您的进程(或任何其他进程)写入内核缓冲池;它与fflush() 完全无关。
  2. sync() 影响系统上所有进程写入的所有数据——如果您的应用程序经常使用它,您可能会变得不受欢迎;它颠覆了内核缓存数据的出色工作。

fflush()

fflush() 函数确保数据已从应用程序的缓冲区写入内核缓冲池(对于单个文件,或者如果您使用 fflush(0)fflush(NULL),则对于所有输出文件)。它不会直接影响其他进程。同样,当您需要确信挂起的输出已发送到内核以进行后续传输时,您可以使用它。您可能会使用它的一个地方是在您希望出现提示的输入操作之前,即使它最后没有换行符。否则,您不经常使用它,但只要您想确保数据已发送到内核进行写入,您就可以使用它。如果您正在调试并且您的程序崩溃,则少量fflush() 语句可以确保在崩溃之前写入挂起的输出。这有助于更准确地揭示问题所在(但使用调试器也可以)。

请注意,设置无缓冲输出(setbuf(stdout, NULL)setvbuf(stdout, NULL, _IONBF, 0))意味着所有输出都“立即”发生。这不一定对性能有好处。您有时会使用它,但很少使用。

【讨论】:

    猜你喜欢
    • 2015-08-10
    • 2021-10-01
    • 2010-09-20
    • 1970-01-01
    • 2011-07-08
    • 2021-09-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多