2011-11-11 52 views
1

我知道內核保證,如果不是在一定程度上,一定數量的數據被原子地寫入,這意味着其他進程正在嘗試讀取數據塊的大小(注意PIPE_BUF,4096Bytes)。但是我一直在想,如果我在存儲設備中寫入更多的數據塊(比如說「abc ... [x bytes] ... xyz」),那麼在內核執行操作的時候,內核會先寫abc,xyz最後一次?Linux系統調用寫入:內核是否保證數據寫入順序?

如果不是,那麼在寫入操作完成之前,某些其他進程可能會讀取「* ... [x字節] ... xyz」。我想,這對於許多應用程序來說無疑是一場災難。

是否有人知道實現,或者,我在哪裏可以在內核源代碼中找到答案?

期待您的回覆!謝謝!

[更新2011.11.12]

我看着源代碼,但我不能完全理解它。我發現調用鏈「write - > vfs_write - > do_sync_write [loops] - > generic_file_aio_write [inode_mutex] - > __generic_file_aio_write - > .. - > generic_perform_write - > .. - > __copy_from_user(to,from,n)

__copy_from_user __copy_from_user是一個用架構依賴asm代碼實現的宏/函數,現在我不能理解它們,但我認爲編碼器會這樣做,因爲我們大多數人都認爲它應該是...

Hopes對於furthur澄清〜

+2

看看「吃我的數據」爲起點:http://flamingspork.com/talks/ –

+0

謝謝。我閱讀了演示文稿。它很實用並且描述了許多問題,但對我來說還不夠深入。 – felix021

回答

2

正確的順序始終服從。

但是,在一個非原子寫到具有多個寫入器的接收器時,可能發生接收的數據包含例如"abc...[n bytes]...[data from other writer]...[m bytes]...xyz",其中n+m=x

所以數據被插入一個完全不同的數據塊。

在原子寫入上,這樣的事情不會發生。

編輯:要清楚,這是關於管道和FIFO只。關於文件,我不知道。

+0

so ...在什麼情況下內核會將寫入視爲原子? – felix021

+0

正如你在你的問題中所說 - 如果寫入大小低於'PIPE_BUF':[{PIPE_BUF}個字節或更少的寫請求不應該與其他進程寫入同一管道的數據交錯。大於{PIPE_BUF}字節的寫入可能會在任意邊界上與其他進程寫入數據,而不管文件狀態標誌的O_NONBLOCK標誌是否已設置。](http://pubs.opengroup.org/onlinepubs /007904975/functions/write.html) – glglgl

+0

謝謝。我閱讀手冊頁,它將PIPE_BUF僅與管道/ FIFO相關聯(「有以下例外」,它說)。我不知道是否有一些類似的常規文件... – felix021

3

的數據可能不是物理刷新到你寫的序盤,所以如果在寫作中的機器崩潰,你可能看到「XYZ」無「ABC」在系統啓動後回升。但假設機器保持運行,內核將確保所有寫入都按正確的順序進行。

+0

是的,我完全理解內核的緩存實現;但我需要一些證據來確認寫入順序......我應該查看源代碼嗎? – felix021

0

可以說我正在寫abc,這是4k,def,這是4k。

內核不會保證,如果我在8k塊中寫入「abcdef」,那另一個進程將看不到「abc」,然後看到「def」作爲兩個單獨的寫入。

但如果我只是寫的「ABC」內核保證任何其他進程將永遠不會看到「A」,然後「B」,然後「C」

http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_14.html#SEC215

你在不同的4K跟蹤。你需要的保證是「xyz」永遠不會在「abc」之前被讀取。這是完全不同的保證。事實上,這不僅僅是一種保證。這是不言而喻的。而且它與沖洗磁盤塊無關。這是該系統的不同級別。