Linux内核 文件一致性之主动一致性

本文探讨了Linux内核如何通过page cache解决文件数据与磁盘一致性问题,重点介绍了fsync、fdatasync和sync接口。fsync确保文件及元数据同步,fdatasync仅同步文件数据,sync则同步所有脏数据。文章详细解析了fsync的实现流程,包括脏页面定位、数据写入和元数据同步等步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        众所周知,Linux内核采用了page cache来缓存文件数据以及元数据。既然采用缓存,就有可能会产生缓存数据与磁盘中的数据不一致的问题,本系列博客中我们重点关注Linux内核如何解决这种不一致。

        一般来说,一个成熟的系统需要提供多种机制来保证数据一致性,其一是用户可控的,即用户能通过特定的接口去控制文件数据的一致性,这是对于文件数据一致性要求比较高的应用需要的语义。另一方面,某些用户或者应用程序对文件数据的一致性要求可能没有那么高,无需在每次写入的时候都调用相应的接口去保证文件缓存数据和磁盘上数据的一致性,此时,操作系统必须能够主动地承担起保证文件一致性的任务。

        下面我们再来讨论下一致性的概念。操作系统中的文件除了数据外(最常见的形式就是字节流),还包含元数据,即文件=数据+元数据,元数据用来描述文件的各种属性,也必须存储在磁盘上。因此,我们说保证文件一致性其实包含了两个方面:数据一致+元数据一致。关于文件数据和元数据在内存中的缓存机制请参考我的另外一篇博客。

        当前Linux下以两种方式实现文件一致性:1. 向用户提供特定接口,用户可通过接口来主动地保证文件一致性;2.系统中存在定期任务(表现形式为内核线程),周期性地同步文件系统中文件脏数据块。这两种方式各有优劣,1可保证文件数据的强一致性,但效率较为低下,每次写入必须等待落实磁盘,2克服了1的低效,但无法保证文件数据的always onsistent。

文件系统一致性接口

       当前Linux主要对用户提供如下接口来保证文件数据一致性(均位于fs/sync.c文件)。

  1. fsync(intfd)
  2. fdatasync(int fd)
  3. sync()

       fsync(fd)将fd代表的文件的脏数据和脏元数据全部刷新至磁盘中。fdatasync(fd)将fd代表的文件的脏数据刷新至磁盘,同时对必要的元数据刷新至磁盘中,这里所说的必要的概念是指:对接下来访问文件有关键作用的信息,如文件大小,而文件修改时间等不属于必要信息。sync()则是对系统中所有的脏的文件数据元数据刷新至磁盘中。本篇博客中我们讲述文件系统的主动一致性也就是详细分析上述三个接口的实现原理。

fsync(int fd)

       fsync的语义是同步fd代表的文件。要实现这种同步,让我们来看看需要有哪些棘手的问题需要解决:

1.   快速定位脏缓存数据。当前Linux以页面为单位组织文件缓存,且将所有的页面组织在radix tree中,那么该问题就变为如何快速定位脏页面?

2.   如何设计一个简单高效的框架来将主动同步和系统中的刷新线程纳入同步框架之中?

       本篇博客中我们不太去关注问题2,待到下一篇中我们会详细思考同步框架的设计。因此下面我们简单描述fsync的实现。追踪它的实现流程如下:

       fsync(int fd)(位于fs/sync.c中)

             ------->do_fsync(fd, 0)(位于fs/sync.c中)

                 ------->vfs_fsync(file, datasync)(位于fs/sync.c中)

                     ------->vfs_fsync_range(file, 0, LLONG_MAX, datasync)(位于fs/sync.c中)

                          ------->filemap_write_and_wait_range(mapping,start, end)(位于mm/filemap.c中)

                             ------->__filemap_fdatawrite_range(mapping,lstart, lend,WB_SYNC_ALL)(位于mm/filemap.c中)

                                 ------->filemap_fdatawait_range(mapping,lstart,lend)(位于mm/filemap.c中)

                                     ------->ext2_fsync(struct file*file, int datasync)(针对ext2文件系统,位于fs/ext2/file.c)

                                       ------->generic_file_fsync(file, datasync)(位于fs/libfs.c中)

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值