【问题标题】:ext4/fsync situation unclear in Android (Java)Android (Java) 中的 ext4/fsync 情况不清楚
【发布时间】:2011-01-16 19:52:21
【问题描述】:

Tim Bray 的文章 "Saving Data Safely" 给我留下了未解决的问题。今天,已经一个多月了,我还没有看到任何后续,所以我决定在这里讨论这个话题。

文章的一点是在使用 FileOutputStream 时应该调用 FileDescriptor.sync() 以确保安全。起初,我很生气,因为在我做 Java 的 12 年里,我从未见过任何 Java 代码进行同步。特别是因为处理文件是一件非常基本的事情。此外,FileOutputStream 的标准 JavaDoc 从未暗示同步 (Java 1.0 - 6)。经过一番研究,我认为 ext4 实际上可能是第一个需要同步的主流文件系统。 (是否有其他建议显式同步的文件系统?)

我很欣赏对此问题的一些一般性想法,但我也有一些具体问题:

  1. Android 何时会同步到文件系统?这可以是周期性的,并且还基于生命周期事件(例如,应用的进程进入后台)。
  2. FileDescriptor.sync() 是否负责同步元数据?那就是同步更改文件的目录。与 FileChannel.force() 进行比较。
  3. 通常,不直接写入 FileOutputStream。这是我的解决方案(你同意吗?):
    FileOutputStream fileOut = ctx.openFileOutput(file, Context.MODE_PRIVATE);
    BufferedOutputStream out = new BufferedOutputStream(fileOut);
    try {
        out.write(something);
        out.flush();
        fileOut.getFD().sync();
    } finally {
        out.close();
    }
    

【问题讨论】:

    标签: java android fileoutputstream fsync ext4


    【解决方案1】:

    Android 会在需要时进行同步,例如屏幕关闭、关闭设备等。如果您只是查看“正常”操作,则永远不需要应用程序显式同步。

    当用户将电池从他们的设备中取出(或对内核进行硬重置)并且您希望确保不会丢失任何数据时,就会出现问题。

    所以首先要意识到:问题是突然断电,因此无法完全关闭,以及此时持久存储中会发生什么的问题。

    如果您只是编写一个独立的新文件,那么您做什么并不重要。用户可能在你写的过程中,就在你开始写之前等拔了电池。如果你不同步,那只是意味着从你写完之后拔电池还有更长的时间将丢失数据。

    这里最大的问题是您想要更新文件的时间。在这种情况下,当您下次读取文件时,您希望 或者 以前的 内容, 新的内容。您不想半途而废,也不想丢失数据。

    这通常通过将数据写入新文件,然后从旧文件切换到该文件来完成。在 ext4 之前,您知道,一旦您完成了文件的写入,对其他文件的进一步操作将在该文件上的操作之前不会在磁盘上进行,因此您可以安全地删除以前的文件或以其他方式执行依赖于新文件的操作完全写好了。

    但是现在如果你写新文件,然后删除旧文件,然后拔掉电池,当你下次启动时,你可能会看到旧文件被删除并创建了新文件,但新文件的内容却没有完全的。通过进行同步,您可以确保新文件此时已完全写入,因此可以根据该状态进行进一步的更改(例如删除旧文件)。

    【讨论】:

    • 我本来希望 flush() 确保所有内容都写入磁盘 - 主要是通过调用 sync()。不是这样吗?
    • @a_horse_with_no_name:不,不是。 flushsync 是两个不同的操作:flush 只是刷新中间缓冲区;同步实际上写入存储。参见例如stackoverflow.com/questions/2340610/…
    【解决方案2】:

    fileOut.getFD().sync(); 应该在 finally 子句中,在 close() 之前。

    考虑到耐用性,sync()close() 重要得多。

    因此,每次您想要“完成”文件的工作时,您都应该在close()@ 之前先sync()

    posix 不保证在您发出close() 时将待处理的写入写入磁盘。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-05-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-02
      • 2011-05-09
      相关资源
      最近更新 更多