fsync 和 syncfs 有什么区别?

What is the difference between fsync and syncfs?

fsync 和 syncfs 有什么区别?

int syncfs(int fd);
int fsync(int fd);

fync 的联机帮助页说明如下:

fsync() transfers ("flushes") all modified in-core data of (i.e., modified buffer cache pages for) the file referred to by the file descriptor fd to the disk device (or other permanent stor‐ age device) so that all changed information can be retrieved even after the system crashed or was rebooted. This includes writing through or flushing a disk cache if present. The call blocks until the device reports that the transfer has completed. It also flushes metadata information associated with the file (see stat(2)).

syncfs 的联机帮助页说明如下:

sync() causes all buffered modifications to file metadata and data to be written to the underly‐ ing filesystems.

syncfs() is like sync(), but synchronizes just the filesystem containing file referred to by the open file descriptor fd.

对我来说两者似乎是平等的。他们正在同步文件描述符引用的文件和关联的元数据。

首先,fsync() (and sync()) are POSIX-standard functions while syncfs() 仅 Linux。

所以可用性是一个很大的不同。

来自POSIX standard for fsync()

The fsync() function shall request that all data for the open file descriptor named by fildes is to be transferred to the storage device associated with the file described by fildes. The nature of the transfer is implementation-defined. The fsync() function shall not return until the system has completed that action or until an error is detected.

请注意,这只是一个请求。

来自 the POSIX standard for sync():

The sync() function shall cause all information in memory that updates file systems to be scheduled for writing out to all file systems.

The writing, although scheduled, is not necessarily complete upon return from sync().

再说一遍,这并不能保证一定会发生。

The Linux man page for syncfs() (and sync()) states

sync() causes all pending modifications to filesystem metadata and cached file data to be written to the underlying filesystems.

syncfs() is like sync(), but synchronizes just the filesystem containing file referred to by the open file descriptor fd.

请注意, 函数 returns 未指定时。

The Linux man page for fsync() states:

fsync() transfers ("flushes") all modified in-core data of (i.e., modified buffer cache pages for) the file referred to by the file descriptor fd to the disk device (or other permanent storage device) so that all changed information can be retrieved even if the system crashes or is rebooted. This includes writing through or flushing a disk cache if present. The call blocks until the device reports that the transfer has completed.

As well as flushing the file data, fsync() also flushes the metadata information associated with the file (see inode(7)).

Calling fsync() does not necessarily ensure that the entry in the directory containing the file has also reached disk. For that an explicit fsync() on a file descriptor for the directory is also needed.

请注意,Linux 为 fsync() 提供的保证比为 sync()syncfs() 提供的保证强得多,并且 POSIX 为 fsync()sync().

总结:

  1. POSIX fsync(): "please write data for this file to disk"
  2. POSIX sync(): "write all data to disk when you get around to it"
  3. Linux sync(): "write all data to disk (when you get around to it?)"
  4. Linux syncfs(): "write all data for the filesystem associated with this file to disk (when you get around to it?)"
  5. Linux fsync(): "write all data and metadata for this file to disk, and don't return until you do"

请注意,Linux 手册页未指定何时 sync()syncfs() return。

我认为目前的答案并不完整。对于 Linux:

According to the standard specification (e.g., POSIX.1-2001), sync() schedules the writes, but may return before the actual writing is done. However Linux waits for I/O completions, and thus sync() or syncfs() provide the same guarantees as fsync called on every file in the system or filesystem respectively.

Before version 1.3.20 Linux did not wait for I/O to complete before returning.

这在 "notes" 和 "bugs" 部分的 sync(2) page 中提到。