C语言 fflush 和 fsync 的区别
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2340610/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Difference between fflush and fsync
提问by Adil
I thought fsync()does fflush()internally, so using fsync()on a stream is OK. But I am getting an unexpected result when executed under network I/O.
我认为fsync()在fflush()内部可以,所以fsync()在流上使用是可以的。但是在网络 I/O 下执行时,我得到了一个意想不到的结果。
My code snippet:
我的代码片段:
FILE* fp = fopen(file, "wb");
/* multiple fputs() calls like: */
fputs(buf, fp);
...
...
fputs(buf.c_str(), fp);
/* get fd of the FILE pointer */
fd = fileno(fp);
#ifndef WIN32
ret = fsync(fd);
#else
ret = _commit(fd);
fclose(fp);
But it seems _commit()is not flushing the data (I tried on Windows and the data was written on a Linux exported filesystem).
但它似乎_commit()没有刷新数据(我在 Windows 上尝试过,数据是写在 Linux 导出的文件系统上)。
When I changed the code to be:
当我将代码更改为:
FILE* fp = fopen(file, "wb");
/* multiple fputs() calls like: */
fputs(buf, fp);
...
...
fputs(buf.c_str(), fp);
/* fflush the data */
fflush(fp);
fclose(fp);
it flushes the data.
它刷新数据。
I am wondering if _commit()does the same thing as fflush(). Any inputs?
我想知道是否_commit()与fflush(). 任何输入?
回答by nos
fflush()works on FILE*, it just flushes the internal buffers in the FILE*of your application out to the OS.
fflush()工作FILE*,它只是将FILE*应用程序中的内部缓冲区刷新到操作系统。
fsyncworks on a lower level, it tells the OS to flush its buffers to the physical media.
fsync在较低级别上工作,它告诉操作系统将其缓冲区刷新到物理介质。
OSs heavily cache data you write to a file. If the OS enforced every write to hit the drive, things would be veryslow. fsync(among other things) allows you to control when the data should hit the drive.
操作系统大量缓存您写入文件的数据。如果操作系统强制每次写入驱动器,事情就会非常缓慢。fsync(除其他外)允许您控制数据何时应该到达驱动器。
Furthermore, fsync/commit works on a file descriptor. It has no knowledge of a FILE*and can't flush its buffers. FILE*lives in your application, file descriptors live in the OS kernel, typically.
此外, fsync/commit 对文件描述符起作用。它不知道 aFILE*并且无法刷新其缓冲区。FILE*通常,文件描述符位于您的应用程序中,文件描述符位于 OS 内核中。
回答by Raedwald
The standard C function fflush()and the POSIX system call fsync()are conceptually somewhat similar. fflush()operates on C file streams (FILEobjects), and is therefore portable.
fsync()operate on POSIX file descriptors.
Both cause buffered data to be sent to a destination.
标准 C 函数fflush()和 POSIX 系统调用fsync()在概念上有些相似。fflush()对 C 文件流(FILE对象)进行操作,因此是可移植的。
fsync()对 POSIX 文件描述符进行操作。两者都会导致缓冲数据被发送到目的地。
On a POSIX system, each C file stream has an associated file descriptor, and all the operations on a C file stream will be implemented by delegating, when necessary, to POSIX system calls that operate on the file descriptor.
在 POSIX 系统上,每个 C 文件流都有一个关联的文件描述符,对 C 文件流的所有操作都将在必要时委托给对文件描述符进行操作的 POSIX 系统调用来实现。
One might think that a call to fflushon a POSIX system would cause a writeof any data in the buffer of the file stream, followed by a call of fsync()for the file descriptor of that file stream. So on a POSIX system there would be no need to follow a call to fflushwith a call to fsync(fileno(fp)). But is that the case: is there a call to fsyncfrom fflush?
人们可能认为fflush在 POSIX 系统上调用会导致write文件流缓冲区中的任何数据的 a ,然后是该文件流的文件描述符的调用fsync()。因此,在 POSIX 系统上,没有必要在调用之后fflush调用fsync(fileno(fp)). 但情况是否如此:是否有对fsyncfrom的调用fflush?
No, calling fflushon a POSIX system does not imply that fsyncwill be called.
不,fflush在 POSIX 系统上调用并不意味着fsync会被调用。
The C standard for fflushsays (emphasis added) it
的 C 标准fflush说(强调)它
causes any unwritten data for [the] stream to be delivered to the host environment to be writtento the file
导致 [the] 流的任何未写入数据被传送到主机环境以写入文件
Saying that the data is to bewritten, rather than that is iswritten implies that further buffering by the host environment is permitted. That buffering by the "host environment" could include, for a POSIX environment, the internal buffering that fsyncflushes. So a close reading of the C standard suggests that the standard does not require the POSIX implementation to call fsync.
说的数据是要被写入,而不是被被写入意味着由主机环境进一步缓冲是允许的。对于 POSIX 环境,“主机环境”的缓冲可能包括fsync刷新的内部缓冲。因此,仔细阅读 C 标准表明该标准不需要 POSIX 实现调用fsync.
The POSIX standard description of fflushdoes not declare, as an extension of the C semantics, that fsyncis called.
所述的POSIX标准描述fflush不声明,作为一个扩展的C语义,即fsync被调用。
回答by pulse
I could say that for simplicity:
为简单起见,我可以这么说:
use fsync()with not streaming files (integer file descriptors)
使用fsync()与不流文件(整数文件描述符)
use fflush()with file streams.
fflush()与文件流一起使用。
Also here is the help from man:
这里还有来自 man 的帮助:
int fflush(FILE *stream); // flush a stream, FILE* type
int fsync(int fd); // synchronize a file's in-core state with storage device
// int type
回答by chqrlie
fflush()and fsync()can be used to try and ensure data is written to the storage media (but it is not always be possible):
fflush()并且fsync()可用于尝试确保将数据写入存储介质(但并非总是可行):
- first use
fflush(fp)on the output stream (fpbeing aFILE *obtained fromfopenor one of the standard streamsstdoutorstderr) to write the contents of the buffer associated with the stream to the OS. - then use
fsync(fileno(fp))to tell the OS to write its own buffers to the storage media.
- 第一次使用
fflush(fp)的输出流(fp被一个FILE *从所获得fopen或标准流中的一个stdout或stderr)写入与该流到OS相关联的缓冲器中的内容。 - 然后用于
fsync(fileno(fp))告诉操作系统将自己的缓冲区写入存储介质。
Note however that fileno()and fsync()are POSIX functions that might not be available on all systems, notably Microsoft legacy systems where alternatives may be named _fileno(), _fsync()or _commit()...
但是请注意,fileno()和fsync()是 POSIX 函数,可能并非在所有系统上都可用,特别是 Microsoft 旧系统,其中可能会命名为替代品_fileno(),_fsync()或者_commit()...
回答by user3428045
To force the commitment of recent changes to disk, use the sync() or fsync() functions.
要强制将最近的更改提交到磁盘,请使用 sync() 或 fsync() 函数。
fsync()will synchronize all of the given file's data and metadata with the permanent storage device. It should be called just before the corresponding file has been closed.
fsync()将所有给定文件的数据和元数据与永久存储设备同步。它应该在相应的文件关闭之前调用。
sync()will commit all modified files to disk.
sync()会将所有修改过的文件提交到磁盘。
回答by poordeveloper
I think below document from python (https://docs.python.org/2/library/os.html) clarifies it very well.
我认为来自 python ( https://docs.python.org/2/library/os.html) 的以下文档很好地阐明了它。
os.fsync(fd) Force write of file with filedescriptor fd to disk. On Unix, this calls the native fsync() function; on Windows, the MS _commit() function.
If you're starting with a Python file object f, first do f.flush(), and then do os.fsync(f.fileno()), to ensure that all internal buffers associated with f are written to disk.
Availability: Unix, and Windows starting in 2.2.3.
os.fsync(fd) 强制将带有文件描述符 fd 的文件写入磁盘。在 Unix 上,这会调用原生的 fsync() 函数;在 Windows 上,MS _commit() 函数。
如果您从 Python 文件对象 f 开始,首先执行 f.flush(),然后执行 os.fsync(f.fileno()),以确保与 f 关联的所有内部缓冲区都写入磁盘。
可用性:Unix 和 Windows 从 2.2.3 开始。

