如何知道何时需要缓冲区刷新?

时间:2018-10-02 03:55:13

标签: c linux buffer fflush

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

  1. fflush()
  2. sync()

我怎么知道什么时候需要打个电话?

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

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

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

那么,如何确定系统何时刷新文件数据/元数据缓冲区,何时不刷新,并且需要显式调用 sync()

>

报价人(未指定何时需要显式调用)

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显示了一种通过使用stdout来禁用setbuf(stdout, NULL);缓冲的方法。 sync是否有类似内容(用于什么缓冲区?)?

1 个答案:

答案 0 :(得分:2)

sync()

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

两个警告:

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

fflush()

fflush()函数可确保已将数据从应用程序的缓冲区(如果使用fflush(0)或{{1},则用于单个文件或所有输出文件)写入内核缓冲池}。它不会直接影响其他进程。同样,当您需要确定未决输出已发送到内核以进行后续传输时,可以使用此方法。您可能会使用它的一个地方是在输入操作之前,您希望该提示出现,即使最后没有换行也是如此。否则,您不会经常使用它,但是只要您想确保已将数据发送到内核进行写入,就可以使用它。如果您正在调试并且程序崩溃,那么fflush(NULL)语句的散布可以确保在崩溃之前写入待处理的输出。这可以帮助更准确地揭示问题出在哪里(但是使用调试器也可以)。

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