fflush和fsync之间的区别

Adi*_*dil 50 c windows fsync fflush

我认为fsync()在内部执行fflush(),因此在流上使用fsync()是可以的.但是我在网络I/O下执行时会得到意想不到的结果.

我的代码片段:

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);
Run Code Online (Sandbox Code Playgroud)

但似乎_commit()并没有刷新数据(我在Windows上试过并且数据是在Linux导出的文件系统上编写的).

当我将代码更改为:

FILE* fp = fopen(file, "wb");
/* multiple fputs() calls like: */
fputs(buf, fp);   
...   
...
fputs(buf.c_str(), fp);
/* fflush the data */
fflush(fp);
fclose(fp);
Run Code Online (Sandbox Code Playgroud)

这次它会刷新数据.

我想知道_commit()是否与fflush()做同样的事情.有什么投入?

nos*_*nos 79

fflush()继续工作FILE*,它只是将FILE*应用程序中的内部缓冲区刷新到操作系统.

fsync 它工作在较低级别,它告诉操作系统将其缓冲区刷新到物理介质.

操作系统会大量缓存您写入文件的数据.如果操作系统强制每次写入命中驱动器,事情就会非常缓慢.fsync(除此之外)允许您控制数据何时应该到达驱动器.

此外,fsync/commit适用于文件描述符.它不知道a FILE*并且不能刷新缓冲区.FILE*通常存在于您的应用程序中,文件描述符存在于操作系统内核中.

  • @patrickvacek实际上你可以使用`int fileno(FILE*stream);`来自`stdio.h`从`FILE*`获取文件描述符. (6认同)
  • @jotik:你应该使用**(标准)`FILE*`函数,*或*(操作系统)文件句柄.你不要混用它们.并且`fileno()`不是标准函数.不幸的是,人们因"扩展"标准标题而出了名的松懈...... (2认同)
  • @DevSolar - `fileno()`是POSIX标准的一部分,因此虽然它不一定是可移植的,但它在某些平台上是标准的. (2认同)

Rae*_*ald 5

标准C函数fflush()和POSIX系统调用fsync() 在概念上有些相似.fflush()在C文件流(FILE对象)上运行,因此是可移植的. fsync()对POSIX文件描述符进行操作.两者都会导致缓冲数据被发送到目的地.

在POSIX系统上,每个C文件流都有一个关联的文件描述符,并且必要时,通过委托对文件描述符进行操作的POSIX系统调用来实现C文件流上的所有操作.

有人可能会认为fflush对POSIX系统的调用会导致write文件流缓冲区中的任何数据,然后调用fsync()该文件流的文件描述符.因此,在POSIX系统上,无需通过呼叫来跟随fflush呼叫fsync(fileno(fp)).但情况是这样的:是否有fsync来自的电话fflush

不,调用fflushPOSIX系统并不意味着fsync会调用它.

C标准fflush说(重点补充)它

导致[流]的任何未写入数据被传递到主机环境以写入文件

说的数据是要被写入,而不是是写入意味着由主机环境进一步缓冲是允许的.对于POSIX环境,"主机环境"的缓冲可以包括fsync刷新的内部缓冲.因此仔细阅读C标准表明该标准不需要POSIX实现来调用fsync.

所述的POSIX标准描述fflush不声明,作为与c语义的扩展,即fsync被调用.