ext4/fsync情况不清楚Android(Java)
-
11-10-2019 - |
题
蒂姆·布雷的文章 “安全保存数据” 给我留下了悬而未决的问题。今天,它已经一个月了,我还没有看到任何后续行动,所以我决定在这里讨论这个话题。
本文的一个点是,使用fileOutputStream时,应要求fileDescriptor.sync()在安全方面处于安全方面。起初,我非常恼火,因为在我做Java的12年中,我从未见过任何Java代码执行同步。尤其是因为应对文件是一件非常基本的事情。另外,FileOutputStream的标准Javadoc从未暗示同步(Java 1.0-6)。经过一些研究,我认为EXT4实际上可能是第一个需要同步的主流文件系统。 (是否有其他文件系统建议明确同步?)
我感谢对此事的一些一般性想法,但我也有一些具体的问题:
- Android何时将同步到文件系统?这可能是周期性的,还基于生命周期事件(例如,应用程序的流程用于背景)。
- fileScriptor.sync()是否照顾同步元数据?那就是同步更改文件的目录。比较filechannel.force()。
- 通常,一个人不会直接写入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(); }
解决方案
Android在需要时会执行同步 - 例如屏幕关闭,关闭设备等。
当用户将电池从设备中拉出(或对内核进行硬重置)时,问题就会出现,并且您想确保不会丢失任何数据。
因此,要意识到的第一件事是:问题是当权力突然丢失时,就不会发生干净的关闭,以及那时持续存储中会发生什么的问题。
如果您只是编写一个独立的新文件,那么您做什么并不重要。用户可能在写作中间,在开始写作之前就可以拉电池。将丢失数据。
这里最关心的是您要更新文件时。在这种情况下,当您下次阅读文件时 任何一个 这 以前的 内容, 或者 这 新的 内容。您不想获得一半写的东西或丢失数据。
这通常是通过在新文件中写入数据,然后从旧文件切换到该数据来完成的。在使用EXT4之前,您知道,一旦完成文件,在该文件上的文件中,其他文件的进一步操作才会在磁盘上进行,因此您可以安全地删除先前的文件或其他依赖新文件的操作被完全写作。
但是现在,如果您编写新文件,然后删除旧文件,然后将电池拉动,当您下一个启动时,您可能会看到旧文件已删除并创建了新文件,但新文件的内容尚未完成。通过执行同步,您可以确保在此时完全编写新文件,因此可以进行进一步的更改(例如删除旧文件),取决于该状态。
其他提示
fileOut.getFD().sync();
应该在最后条款上,在 close()
.
sync()
比 close()
考虑耐用性。
因此,每当您想在文件上工作时,您都应该 sync()
以前 close()
它。
Posix不能保证在发布A时将写信给磁盘 close()
.