fsync和write系统调用的区别

7
我想问一个基本问题,什么时候使用像fsync这样的系统调用是有用的。我是初学者,一直以来都认为write足够写入文件,而使用write的示例实际上是在文件末尾写入。
那么,像fsync这样的系统调用的目的是什么?
只是提供一些背景,我正在使用Berkeley DB库版本5.1.19,并且有很多关于fsync()成本与仅写入的讨论。这就是我想知道的原因。
1个回答

16

将其视为缓冲层。

如果您熟悉标准C调用,例如fopenfprintf,则应该已经了解到C运行时库本身中发生的缓冲。

刷新这些缓冲区的方法是使用fflush,它确保信息从C运行时库传递给操作系统(或周围环境)。

但是,仅因为操作系统拥有它,并不意味着它位于磁盘上。 它也可能在操作系统内部被缓冲。

这就是fsync要处理的内容,确保操作系统缓冲区中的内容物理写入磁盘。

通常可以在日志记录库中看到此类操作:

fprintf (myFileHandle, "something\n");  // output it
fflush (myFileHandle);                  // flush to OS
fsync (fileno (myFileHandle));          // flush to disk

fileno 是一个函数,它可以为给定的 FILE* 文件句柄提供底层的 int 文件描述符,对描述符进行 fsync 操作可以完成最终级别的刷新。

由于磁盘写入通常比内存传输要慢得多,因此这是一项相对较昂贵的操作。

  

记录日志库以及其他用例也可能需要使用此行为。让我看看我是否能记起来是什么。是的,就是那个。数据库!就像Berzerkely DB一样。您希望确保数据在磁盘上的存储,这是满足ACID要求的一个非常有用的功能 :-)


谢谢,这很有帮助。如果我没有显式调用fsync,那么操作系统(在我的情况下是Linux)什么时候决定将数据刷新到磁盘上? - isaac.hazan
1
@isaac.hazan,我脑海中没有想法。可能是当缓冲区填满时,文件描述符关闭时,经过一定时间后或者随时都有可能发生 :-) 这也可能会因为你使用的任何文件系统的设备驱动程序而改变。基本上,除非你需要立即完成,否则你不应该担心何时进行同步,此时你应该使用fsync。否则,就让操作系统来处理吧。 - paxdiablo
1
@paxidablo:1)“当文件描述符关闭时”:这是最普遍的误解之一。close并不意味着缓冲页面已被写入。2)fsync的替代方法是使用带有O_SYNC标志的文件打开。3)在糟糕的消费者磁盘/固态硬盘中,即使进行fsync也可能无法强制数据持久化。在这种情况下,用户/开发人员基本上无能为力。 - dmeister
@dmeister,那些只是可能性而不是明确的陈述。我需要查看内核源代码以确认,但考虑到默认行为通常足够(除非系统严重崩溃),这比它值得的更多努力。如果您决定需要fsync并且它失败了,那么您几乎没有其他选择 :-) - paxdiablo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接