如何使用C语言在Linux中原子地异步写入文件

5

问题

如何在不需要程序等待缓慢物理介质(例如使用fsync)的情况下原子更新文件?

我希望操作系统可以在RAM中“缓冲”典型的fsyncrename操作,然后在方便的时候以正确的顺序将它们写入磁盘。


背景

我正在开发运行在定制嵌入式Linux环境中的软件,使用ext4文件系统。该程序会定期更新磁盘上的一个文件。我需要维护这个文件的完整性,同时又不损失应用程序的性能。

根据我所了解到的文章,安全地更新文件的惯例如下:

  1. 创建一个新的临时文件
  2. 向临时文件写入数据
  3. fsync()临时文件
  4. 将临时文件重命名为适当的名称
  5. fsync()包含目录

这个过程对我来说是有意义的,但在我的特定应用程序中,我想避免对fsync()的阻塞调用。只要文件始终处于有效状态,我不关心数据何时写入磁盘。如果文件已过时,那没问题。


到目前为止我学到了什么

似乎已经有很多关于ext4和正确使用fsync的讨论。如果我理解正确,如果我的文件系统启用了auto_da_alloc,我可能可以放弃使用fsync链接),但我并不认为这是最佳解决方案。


1
创建另一个线程。在另一个线程中调用fsync。在fsync之后通知调用线程。还有posix aio。 - KamilCuk
2
@Peteman720 在这种情况下,我会按照你在帖子中描述的步骤进行操作。您可以通过线程运行所有这些步骤,以最小化阻塞效果。 - Serge
2
aio_fsync。而glibc的aio_fsync实现只是为您完成相同的工作 - aio_fsync创建另一个线程,在该线程中调用fsync并为您引发信号。 - KamilCuk
2
@Peteman720,所以fsync的目的是防止程序在时间未到(所有新数据已写入磁盘)之前执行rename等不安全操作。等待不仅仅是一个麻烦,它是算法的关键部分。如果您不打算等待步骤3中的fsync完成,那么首先调用它就没有太多意义。 - user4815162342
1
我认为你应该在问题中提到“缓冲”,因为很明显你正在寻找这种类型的东西。我不认为它存在于Linux或其他类Unix系统中。 - user4815162342
显示剩余8条评论
1个回答

0

我发现Linux文件系统非常强大和可靠。对于那些主要来自2009年的ext4问题讨论,我会持怀疑态度。Linux信息很容易过时。

话虽如此,如果要保证使用最新的正确版本文件,则需要添加一个检查文件是否正确的步骤。一种方法是使用Linux工具生成文件的哈希值。也许有更快的方法适用于您特定的数据,例如查找特定文件长度。

有了这个步骤,您的算法可以是:

  1. 将当前文件重命名以指示它是旧副本。
  2. 编写新文件
  3. 计算新文件的哈希值

现在,当您启动或使用该文件时,可以检查哈希值,如果失败,则恢复到最新的旧副本。

这个计划的优点是哈希将保护您免受文件的任何损坏来源,而不仅仅是ext4文件系统问题。


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