2016-10-20 122 views
0

我正在使用C++ ofstream在Linux上編寫日誌文件。當我使用tail -f命令監視文件內容時,我可以看到正確填充了內容。但是如果發生停電並且在重新上電後再次檢查文件,則最後幾行記錄消失。使用hexdump我可以將這些記錄轉換爲空字符'\ 0'。我嘗試了flush()和manipulator std :: endl,但它們無論如何都沒有幫助。斷電後文件內容丟失

這是真的,尾巴顯示給我的是沒有真正寫入磁盤,他們只是在緩衝區? inode表在停電之前沒有更新?我可以接受這個事實,但我不明白爲什麼記錄轉換爲空字符,如果他們沒有寫入文件。

順便說一句,我試過谷歌的glog,並有相同的結果(一堆空字符在最後)。我也試過zlog,一個C庫。並發現它只丟失了最後的記錄,但沒有用空字符替換它們。

+1

使用同步而不是刷新。可能的重複http://stackoverflow.com/questions/14251873/what-is-the-difference-between-flush-and-sync-in-regard-to-fstream-buffers –

+0

純粹假設的解釋:「尾巴」顯示操作系統緩存的內容或磁盤控制器的緩衝區。該文件已被擴展(帶有零),內容(可能)已被寫入磁盤控制器的緩衝區,但控制器尚未將其緩衝區寫入磁盤。 – molbdnilo

+0

@molbdnilo我認爲您建議立即更新文件系統以反映文件的新大小,但數據從未有機會被磁盤控制器寫入磁盤。然後誰決定實際寫入數據,OS?磁盤控制器固件? –

回答

0

那麼,當你停電並重新啓動系統時,linux內核會嘗試轉發日誌日誌以檢測並糾正系統崩潰時內存與磁盤之間的不一致性。通常這意味着重做並提交所有可能的操作,直到系統崩潰,但撤銷(並擦除)在崩潰時未提交的所有數據。

Linux(和其他聯合國* X的內核,就像FreeBSD的)有一個名爲設施有序的數據寫入,該部隊的元數據(比如從索引節點塊的指針,或目錄項)進行更新它們指向的實際數據被有效地寫在磁盤上,所以不一致減到最小。我不知道實際的Linux實現,但是例如,在freebsd中,您指出的是(freebsd內核完全不可能實現一個文件中的零而不是實際寫入的數據)(也可以故意實現,但並非偶然)最可能的情況是,linux可能只是管理塊信息而不是文件內容,或者它更新了文件大小指針,而不是數據直到那裏。這不應該發生,因爲它已經解決了問題。

另一件事是你寫了多少數據,或者爲什麼你在屏幕上看到的東西在系統崩潰後沒有出現。可能您已經聽說過一些名爲的延遲寫入,它允許內核在繁忙系統上將寫入操作保存到磁盤,方法是不將數據立即寫入磁盤,但需等待一段時間,以便更新可在覈心內存緩衝區中解析,然後進入磁盤。無論如何,磁盤寫入在延遲一段時間後都會被強制執行,這意味着5secs在Linux中(我試着記住,上次有很多時間我檢查了這個值,我對5到30秒之間有疑問),所以你可能會丟失最多五秒鐘。

+0

感謝您的提示。我將在freebsd上進行實驗。是的,我的文件系統是EXT4有序數據模式。我的理解就像你解釋說元數據在寫入實際數據後更新了。但結果似乎相反。麻煩的是,日誌解析器必須處理這種異常,即使它們只是一個塊零)。 –

+0

這確實應該是不正確的,就好像你修復文件系統一樣,你的文件損壞了,這是不好的。如果修復後打開fille並追加到它,它會顯示一個零字節塊,這不是一件好事。 –