2011-08-01 40 views
6

我有兩個進程每個寫入大量緩衝區的數據,我想控制同步這些進程的寫入到一個文件。包括(A1,A2,A3)的處理1寫入緩衝器A和包括(B1,B2,B3)的處理2寫入緩衝器B的處理1。當我們使用write()系統調用將這些緩衝區寫入磁盤到同一文件(整個緩衝區一次:write(fd, A, sizeof(A)))時,文件架構如何?如何同步 - 使原子 - 從兩個進程寫入一個文件?

  • 是這樣的:A,B或B,A也許?
  • ,也可能是這樣的:A1,A2,B1,A3,...

我問這是因爲系統調用是原子的。如果我們寫的數據緩衝區太大,會發生什麼情況。它是否像普通磁盤文件的管道一樣?

回答

4

如果你想兩個緩衝區的內容存在,你必須打開設置了O_APPEND標誌的文件。在寫入之前,追加標誌尋找到文件末尾。沒有這個集合,有可能兩個進程都會指向文件的相同或重疊區域,最後寫入的人將會覆蓋其他人寫入的內容。

每次調用write都會寫入最大請求的字節數。如果你的進程被一個信號中斷,那麼你最終可能會進行部分寫操作 - 返回寫入的實際字節數。無論你是否寫入所有的字節,都會寫入文件的一個連續部分。你沒有得到你提到的交錯效果作爲你的第二種可能性(例如A1,B1,A2,B2,...)。

如果您只能獲得部分書寫,您將如何繼續取決於您。您可以繼續寫入(從緩衝區起始處偏移之前寫入的字節數),也可以放棄其餘的寫入。只有這樣,你纔有可能獲得交錯效應。

如果在寫入其他進程之前完成一次寫入的內容非常重要,那麼在嘗試寫入任何數據之前,應該考慮鎖定文件以進行獨佔寫入訪問(這兩個進程都必須檢查)。

+0

因此,我們沒有任何信號,並且啓用了'O_APPEND',我們應該有A,B或B,A。我對嗎? –

+1

@Majid - 是的,假設系統中沒有任何東西會打斷你,你會得到A,B或B,A取決於誰先走。 – unpythonic

+0

值得注意的是,在本地文件系統上的正常文件寫入不會中斷。 NFS有一個標誌使它們可以被中斷,但是默認是關閉的。 –

2

假設緩衝區的大小相同,結果將是A或B,具體取決於最後一次調度哪個進程。

寫入系統調用是原子的,是的,這意味着結果將是A或B,而不是兩者的混合。

假設您想要文件中的A和B,可以使用O_APPEND打開文件;請注意,這不會通過NFS工作。

另一種選擇是,每個過程跟蹤哪些文件偏移它應該使用,並使用lseek的()或PWRITE()

2

對於訪問該文件的程序,您絕對需要某種形式的同步,否則最終會導致文件內容混亂。系統調用write可能寫入的字節數少於請求的字節數,因此塊A1,A2或B1,B2只能部分寫入。這可能經常發生,或者很少發生,這取決於許多條件。如果它只在一週內發生一次,則會出現一個可能很難檢測到的錯誤。

作爲解決方案,您可以使用文件鎖定(man 2 flockman fcntl並搜索鎖定)。另一種可能性是使用信號量(man -k semaphore)來同步您的程序寫入或某些其他形式的IPC。

+0

+1文件鎖定可能是要走的路,因爲一次性寫下所有內容往往效率低下(或很難)。 –

相關問題