Linux中的fsync系统调用是如何工作的?

11

当“write”调用返回时,数据会被复制到由内核管理的某个页面上。该页面可能包含来自多个进程的写入。因此,当其中一个应用程序发出“fsync”调用时,这是否会导致刷新整个页面,这意味着刷新其他应用程序的数据,但成本将由调用“fsync”的进程承担。这正确吗?

2个回答

9

fsync 操作针对单个文件,会刷新该文件的所有更改。如果多个进程正在向单个文件写入,则进行fsync调用的进程将暂停,直到所有的更改都被写入磁盘

当一些日志文件系统参与时,情况就会变得更加复杂。例如,使用“有序”模式的ext3和ext4(在较小程度上)需要刷新所有在日志中位于fsync文件之前的所有文件的更改

这意味着,如果程序一直在写入大型数据库、大型日志文件或视频文件,然后您尝试使用fsync同步两行配置文件,那么fsync必须等待这些兆字节的数据全部写入磁盘才能返回。

这就是为什么我运行我的ext4在“writeback”模式下,虽然在崩溃后可能会出现一些不愉快的后果,如正确大小但填充了零的文件。但在正常操作中,“writeback”要快得多,以至于我认为这种权衡是值得的。


想象一个虚拟内存页面,其中包含应用程序A和B的写入。如果应用程序A调用fsync,内核是否只会有选择地同步页面?另外,ext4的默认模式是“有序”的吗? - Jimm
@Jimm:在磁盘缓存中,文件永远不会共享内存页面,因此这种情况不会发生。 - Zan Lynx
1
在操作系统内存缓存中属于某个文件的页面要么被标记为脏页(表示该页面已更改),要么未被标记为脏页(未更改)。当A对该文件调用fsync时,属于该文件的所有脏页都会被写入磁盘,无论是哪个进程进行了更改。 - nos
@nos 我的理解是,每个文件没有维护内存页面的概念。想象一下,你创建了一个文件并写入一行。操作系统不会为该写入专门初始化一个内存页面,因为一旦用户发出写入请求,无论它属于哪个文件,文件系统驱动程序都会将其排队等待传递给磁盘驱动程序。来自2个不同进程的两个写入可能会落在同一个内存页面上。 - Jimm
@ZanLynx 你怎么确定?ext4共享内存页面,将数据排队到磁盘驱动程序。 - Jimm
@Jimm,这里有一个缓存层负责处理此事。除非它正在覆盖文件的现有部分,在这种情况下会使用镜像驱动器上数据的现有页面(可能需要先加载),否则将为该写入的数据分配内存。write() 调用不是同步调用,只是将数据写入内存,而操作系统将异步地将数据刷新到驱动器。 - nos

2
该手册说明:“将写入此文件的任何数据刷新到磁盘”,其中包括文件元数据。
我认为你将其与sync混淆了,后者会将整个缓存中的所有脏页面写入磁盘。脏页面指已更改的数据。该过程必须等待全部完成。如果您所说的成本是指等待时间,则是的,这会产生成本。内核时间会添加到进程系统时间资源使用中。
fsync也会产生成本,但比sync(通常)少得多的内核时间。

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