2012-11-13 144 views
1

從本地設備測試中,我已經看到,在文件完全提交之前,將文件寫入iOS文件系統(不管您使用的調用級別有多低)通常會返回成功到閃光燈。意思是,如果您重置設備然後重新啓動,您的文件可能會回滾(如果寫入完成或原子化)或損壞。這個延遲的來源是什麼(文檔讚賞,我一直無法找到任何東西),並且在實際的文件系統寫入完成時有一種獲得反饋的方法。例如,我想確認從遠程服務器接收和存儲一段數據,但是我發現在寫入「報告」成功後確認它會在硬件崩潰或電源故障時導致數據丟失。iOS/iPhone日記/文件系統緩存

回答

3

由於這是一個4年的問題,我不僅會提供答案,還會提供我在搜索時所採取的路徑。

我在官方文檔中找不到任何明確的解釋:File System Programming GuidePerformance Tips section只有一條線索。它指出:

應用程序可以使用F_NOCACHE標誌調用BSD fcntl函數來啓用或禁用文件的緩存。有關此功能的更多信息,請參閱fcntl。

啓用F_NOCACHE標誌不解決你陳述的問題,但是,對於fcntl方法手冊規定有,你可能只是覺得有趣的選項:

F_FULLFSYNC做同樣的事情FSYNC(2)然後要求驅動刷新所有緩衝的數據到永久存儲設備

(從man fcntl,見here)。

我檢查了手冊fsync瞭解更多詳情。它最終給了我對問題和解決方案的最清楚和最容易理解的解釋:

請注意,儘管fsync()會將主機中的所有數據刷新到驅動器(即「永久性存儲設備「),驅動器本身可能在物理上不會將數據寫入盤片相當長的一段時間,並且可能會以無序的順序寫入。

具體而言,如果驅動器斷電或操作系統崩潰,應用程序可能會發現其中只有一些數據或者沒有寫入數據。磁盤驅動器也可能重新排序數據,以便以後的寫入可能存在,而較早的寫入不存在。

這不是理論上的邊緣情況。這種情況很容易在現實世界的工作負載和驅動器電源故障中複製。

對於需要更嚴格保證其數據完整性的應用程序,Mac OS X提供了F_FULLFSYNC fcntl。 F_FULLFSYNC fcntl要求驅動器將所有緩衝數據刷新到永久存儲器。需要嚴格寫入順序的應用程序(如數據庫)應使用F_FULLFSYNC以確保其數據按照預期順序編寫。

(來自man fsync,參見here)。

是的,這絕對不是理論上的邊緣情況。值得慶幸的是,一旦你知道這個問題,解決方法很簡單:

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完成後,您的數據將被保存。

注意這個操作比通常寫入文件要慢(通過NSFileManagerwriteToURL方法系列)。在性能問題的情況下,最好將寫入移動到後臺線程。