[英]iOS / iPhone Journaling / File System Caching
从本地设备测试中,我已经看到将文件写入iOS文件系统(无论您使用的调用级别如何)通常会在文件完全提交到闪存之前返回成功。 意思是,如果你硬重置设备然后重启,你的文件可以回滚(如果写完成或原子)或损坏。 这种延迟的来源是什么(文档很受欢迎,我找不到任何东西),有没有办法在实际的文件系统写入完成时获得反馈。 例如,我想承认从远程服务器接收和存储一段数据,但我发现在写“报告”成功后确认它可能会导致硬件崩溃或电源故障时数据丢失。
由于这是一个4年前的问题,我不仅会提供答案,还会提供我在搜索时所采用的路径。
我无法在官方文档中找到任何明确的解释: 文件系统编程指南 。 “ 性能提示”部分中只有一条线索。 它指出:
应用程序可以使用F_NOCACHE标志调用BSD fcntl函数来启用或禁用文件的缓存。 有关此函数的更多信息,请参阅fcntl。
启用F_NOCACHE
标志并不能解决您所说的问题,但是, fcntl
方法的手册指出了一个您可能感兴趣的选项:
F_FULLFSYNC与fsync(2)相同的事情然后要求驱动器将所有缓冲的数据刷新到永久存储设备
(来自man fcntl
,见这里 )。
我已经查看了fsync
的手册以获取更多详细信息。 它最终给了我关于问题和解决方案的最清晰,最容易理解的解释:
请注意,虽然fsync()会将所有数据从主机刷新到驱动器(即“永久存储设备”),但驱动器本身可能无法将数据物理地写入盘片很长一段时间,并且可能会写出来有序序列。
具体来说,如果驱动器断电或操作系统崩溃,应用程序可能会发现只写了一些或没有写入数据。 磁盘驱动器还可以重新排序数据,以便可以存在以后的写入,而较早的写入则不存在。
这不是理论上的边缘情况。 使用实际工作负载和驱动器电源故障可轻松复制此方案。
对于需要更严格保证其数据完整性的应用程序,Mac OS X提供F_FULLFSYNC fcntl。 F_FULLFSYNC fcntl要求驱动器将所有缓冲的数据刷新到永久存储器。 需要严格写入顺序的应用程序(如数据库)应使用F_FULLFSYNC来确保其数据按预期顺序写入。
(来自man fsync
,请看这里 )。
是的,这绝对不是理论上的边缘情况。 值得庆幸的是,一旦你知道这个问题,解决方案是微不足道的:
let filePath: String = "your file path"
// you can use other option than read-write
let fd = open(String(path.utf8), O_RDWR)
// if fd is -1, there was an error opening file, handle it as you wish
guard fd != -1 else { return }
// syncResult is -1 if sync operation failed, handle it as you wish
let syncResult = fcntl(fd, F_FULLFSYNC)
// don't forget to close opened file
close(fd)
fcntl
完成后,您的数据将被保存。
请注意,此操作比通常写入文件(通过NSFileManager
或writeToURL
方法系列) writeToURL
。 如果出现性能问题,最好将写入移至后台线程。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.