2013-01-21 18 views
2

考慮這個例子:是「文件數據」和「文件大小」提交到磁盤一起或單獨

FILE* stream = fopen("my_file", "w"); 
fputs("hello", stream); 

如果電源的fputs的執行(過程中丟失會發生什麼)?

之後,我能否找到非零大小的「my_file」,但第一個字節不是'h'? 如果是,它保證爲零,還是可以包含任意值?

當然,假設沒有其他人觸摸我們的文件。

編輯:還假定目標磁盤驅動器/設備是能夠保持足夠長的時間足以寫入所有已在內部緩衝的數據的類型。

POSIX對此有什麼要說的嗎? Linux? Windows?

編輯:我不打算專注於如何實現STDIO流API的細節。假設POSIX,這裏是我真正的意思是:

int fd = open("my_file", O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); 
write(fd, "hello", 5); 

編輯:POSIX認爲大小爲文件元數據,因此問題很可能被改寫爲:可以將文件數據和元數據,該文件作爲上述代碼的結果,它們會在不同的階段被提交到磁盤上?

編輯:http://www.sqlite.org/atomiccommit.html發現這一點:

7.5文件系統具有安全附加語義

在SQLite的版本中引入的另一個優化3.5.0利用的基本盤的「安全附加」行爲 。回想一下, SQLite假定當數據被附加到文件(特別是回滾日誌的 )時,首先增加文件大小 ,並且內容被寫入第二個。因此,如果在文件大小增加但寫入內容爲 之前電源丟失 ,則文件將保留包含無效的「垃圾」數據。但是,VFS的xDeviceCharacteristics方法可能會指示 文件系統實現「安全附加」語義。此 表示在文件大小增加 之前寫入內容,以便在斷電或系統崩潰時無法將 引入回滾日誌。

這似乎提供了至少部分答案。

+1

[SQLite如何處理原子提交](http://www.sqlite.org/ atomiccommit.html)可能是有趣的。 – user786653

+0

良好的鏈接 - 謝謝! –

回答

1

對於linux,寫入緩衝區的內容不保證寫入磁盤immediatley。

kernel複製databuffer,後來在後臺,內核收集了所有的dirty buffers的,最好將它們排序,並寫出來,以disk。這就是writeback。這可以使寫入調用快速發生,幾乎立即返回。它也允許內核defer writes更多idle periods和批量許多writes together

+0

好的信息,但我的問題是具體關於一個文件可能最終從零增加,但其內容從未寫入,例如,由於電源故障。我想這個問題的答案與內核如何執行這個「writeback」過程的複雜細節有很大關係。我希望,例如,POSIX在這方面確實提出了一些保證。 –

0

這在很大程度上取決於所使用的文件系統(ext3ext4xfs,....),並給它安裝時的選項,所以不容易的一刀切,所有的答案。也許如果你告訴我們你的/etc/fstab並告訴我們你想知道哪個文件系統,可以給出更好的答案...

+0

如果可能,我寧願不考慮特定文件系統的細節。我將不得不假定它可以是任何流行的。但是我想你所說的是,對於某些文件系統,確實可以找到非零大小的「my_file」,但在斷電後第一個字節不是「h」。例如,如果您有任何詳細信息可以提供'ext4',那就太好了。 –

相關問題