66

我认为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);

但似乎_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);

它刷新数据。

我想知道是否_commit()fflush(). 有什么输入吗?

4

6 回答 6

101

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

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

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

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

于 2010-02-26T09:41:00.540 回答
9

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

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

有人可能认为fflush对 POSIX 系统的调用会导致write文件流缓冲区中的任何数据的 a ,然后是对该文件流的fsync()文件描述符的调用。因此,在 POSIX 系统上,无需在调用 to 之后再fflush调用fsync(fileno(fp)). 但情况是否如此:是否有调用fsyncfrom fflush

不,fflush在 POSIX 系统上调用并不意味着fsync会被调用。

C 标准fflush表示(强调)它

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

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

POSIX 标准描述fflush没有声明,作为C 语义的扩展fsync被称为。

于 2017-01-12T14:03:39.467 回答
3

为了简单起见,我可以这么说:

与非流式文件一起使用fsync()(整数文件描述符)

fflush()与文件流一起使用。

这也是来自人的帮助:

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
于 2015-02-04T15:29:06.550 回答
3

fflush()并且fsync()可用于尝试并确保将数据写入存储介质(但并非总是可行):

  1. 首先fflush(fp)在输出流上使用(从标准流或其中fp一个FILE *获得)将与流关联的缓冲区的内容写入操作系统。fopenstdoutstderr
  2. 然后用于fsync(fileno(fp))告诉操作系统将自己的缓冲区写入存储介质。

但是请注意,fileno()fsync()是 POSIX 函数,可能并非在所有系统上都可用,尤其是 Microsoft 遗留系统,其中替代品可能被命名为_fileno()_fsync()或者_commit()...

于 2019-06-27T18:59:25.323 回答
1

要强制将最近的更改提交到磁盘,请使用 sync() 或 fsync() 函数。

fsync()会将所有给定文件的数据和元数据与永久存储设备同步。应该在相应文件关闭之前调用它。

sync()会将所有修改的文件提交到磁盘。

于 2015-03-05T14:24:45.907 回答
1

我认为下面来自 python 的文档(https://docs.python.org/2/library/os.html)很好地阐明了这一点。

os.fsync(fd) 强制将带有文件描述符 fd 的文件写入磁盘。在 Unix 上,这会调用本机 fsync() 函数;在 Windows 上,MS _commit() 函数。

如果从 Python 文件对象 f 开始,首先执行 f.flush(),然后执行 os.fsync(f.fileno()),以确保与 f 关联的所有内部缓冲区都写入磁盘。

可用性:从 2.2.3 开始的 Unix 和 Windows。

于 2017-11-23T02:20:56.760 回答