我正在瀏覽這本書The Linux Programming Interface。在頁號。第73章第4話
fd = open("w.log", O_WRONLY | O_CREAT | O_TRUNC | O_APPEND, S_IRUSR | S_IWUSR);
我讀到該O_TRUC標志用于將檔案長度截斷為零,這會破壞檔案中的任何現有資料。
O_APPEND 標志用于將資料附加到檔案的末尾。
內核記錄一個file offset,有時也稱為read-write offset or pointer. 這是檔案中下一個read()或write()將開始的位置。
我很困惑,如果檔案被截斷并且內核在檔案末尾進行后續寫入,為什么需要附加標志來明確告訴在檔案末尾追加?
如果沒有附加標志(如果檔案被截斷),內核將在檔案末尾寫入以供后續write()函式呼叫。
請幫忙,謝謝。
uj5u.com熱心網友回復:
O_APPEND標志用于將資料附加到檔案的末尾。
這是真的,但不夠完整,可能會產生誤導。我懷疑您實際上在這方面感到困惑。
內核記錄一個檔案偏移量,有時也稱為讀寫偏移量或指標。這是檔案中下一個
read()或write()將開始的位置。
這也是不完整的。至少每個可查找檔案都有一個檔案偏移量。那是下一個read()開始的位置。如果檔案沒有以追加模式打開,那么下一個write()將開始的地方,但在追加模式下,每次寫入都發生在檔案的末尾,就好像它在每個之前都被重新定位一樣。那么,在這種情況下,當前檔案偏移量可能不是下一個檔案開始的位置。lseek(fd, 0, SEEK_END)write()
我很困惑,如果檔案被截斷并且內核在檔案末尾進行后續寫入,為什么需要附加標志來明確告訴在檔案末尾追加?
不需要在檔案末尾發生截斷后的第一次寫入(通過任何行程),因為在檔案被截斷后立即沒有任何其他位置。
如果沒有附加標志(如果檔案被截斷),內核將在檔案末尾寫入以供后續的 write() 函式呼叫。
只要檔案沒有重新定位或外部修改,后續寫入也不需要它。否則,下一次寫入的位置取決于檔案是否以追加模式打開。
在實踐中,不一定每個標志的組合都是有用的,但組合O_TRUNC和O_APPEND具有明顯不同的效果,而不是沒有另一個標志,并且組合在某些情況下是有用的。
uj5u.com熱心網友回復:
O_APPEND很少有O_TRUNC. 我認為 Cfopen模式的任何組合都不會產生這種組合(在 POSIX 系統上,這是相關的)。
O_APPEND確保每次寫入都在檔案末尾自動完成,無論寫入位置如何。特別是,這意味著如果多個行程正在寫入檔案,它們不會踩踏彼此的寫入。
請注意,POSIX 不需要
O_APPEND. 它要求在寫入之前自動搜索到檔案的(當前)末尾,但它并不要求在寫入發生時該位置仍然是檔案的末尾。即使在具有 atomic 功能的實作上O_APPEND,它也可能不適用于所有檔案系統。Linux 手冊頁關于在 NFS 上不能以原子方式作業的open警告O_APPEND。
現在,如果每個行程O_TRUNC在打開檔案時都使用,它將破壞所有其他行程寫入的所有內容。這與行程不應該破壞彼此的寫入的想法相沖突,這O_APPEND是指定的。
O_APPEND不需要通過單個行程附加到檔案,該行程被理解為唯一的寫入者。可以只搜索到最后,然后開始寫入新資料。有時O_APPEND在排他情況下使用,僅僅是因為它是一種編程快捷方式。我們不必費心額外呼叫 position 到檔案末尾。比較:
FILE *f = fopen("file.txt", "a");
// check f and start writing
相對:
FILE *f = fopen("file.txt", "r ");
// check f
fseek(f, 0, SEEK_END); // go to the end, also check this for errors
// start writing
我們可以考慮這樣一種想法,即我們有一組行程使用O_APPEND一個檔案,這樣第一個行程也首先執行O_TRUNC截斷它。但是這樣編程似乎很尷尬;一個行程要判斷它是否是第一個打開檔案的行程并不容易。
如果在啟動時需要這種情況,其中啟動之前的舊檔案由于某種原因無關緊要,只需在啟動這些多個行程之前執行啟動時操作(腳本或其他)洗掉舊檔案. 然后每個人都O_CREAT在必要時使用創建檔案(如果它是第一個行程)但沒有O_TRUNC(如果它們不是第一個行程),并使用O_APPEND執行原子(如果可用)附加的事情。
uj5u.com熱心網友回復:
兩者完全獨立。該檔案被簡單地打開,O_APPEND因為它是一個日志檔案。
作者希望并發訊息連接而不是相互覆寫(例如,如果程式分叉),并且如果管理員或日志輪換工具截斷檔案,那么新訊息應該在第 1 行而不是第 1000000 行開始寫入,其中最后一個日志條目被寫入。如果沒有 O_APPEND,這將不會發生。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/407168.html
標籤:
