當您讀取一個被覆蓋的文件時會發生什麼?

當您讀取一個被覆蓋的文件時會發生什麼?

假設我讀取(cat)一個文件,而另一個進程正在重寫其內容。輸出是可預測的嗎?會發生什麼事?

答案1

這取決於作者做什麼。

如果寫入者覆蓋現有文件,那麼當寫入者超過讀取器(如果有的話)時,讀取器將看到新內容。如果作者和讀者以不同的速度進行,讀者可能會交替看到舊內容和新內容。

如果寫入器在開始寫入之前截斷文件,則讀取器將在此時針對文件末尾運行。

如果寫入器建立一個新文件,然後將新文件移至舊名稱,則讀取器將繼續從舊文件中讀取。如果移動或刪除已開啟的文件,則開啟該文件的程序會繼續讀取相同文件。如果檔案被刪除,它實際上保留在磁碟上(但無法再次開啟它),直到最後一個進程將其關閉。

Unix系統往往沒有強制的。如果應用程式想要確保其寫入器元件和讀取器元件不會互相干擾,則開發人員需要使用適當的鎖定。有一些例外情況,核心開啟的檔案可能會受到保護,不被使用者應用程式寫入,例如環形- 已安裝的檔案系統映像或在某些 UNIX 變體上執行的可執行檔。

答案2

這是一種經典的競爭條件,因此根據定義,結果是不可預測的。

其中,這取決於

  • fopen(3)open(2)寫入模式,
  • 作者如何/是否緩衝其輸出,
  • 讀者如何閱讀文件,
  • 讀者和作者之間的速度差異,
  • 讀取和寫入開始之間的時間差。
  • 當然,在現代多核心機器上,由於其他較低因素(例如進程調度),事情變得更加複雜。

如果您需要能夠在重寫文件時讀取該文件,那麼您可以讓編寫器製作該文件的臨時副本,對其進行修改,然後將其複製回原始文件。rsync例如,這種方式就是這樣做的。有很多方法可以實現這一點,但沒有免費的午餐。每種方法都有其自身的缺點和影響。

答案3

以前的響應者有比這更全面的解釋,但這裡有一個絕對有效的技巧,幾乎完全按照他想要的方式進行:

$ tail -f <filename>

將在寫入時向您顯示文件的結尾。例如,如果您想將 STDERR 透過管道傳輸到文件,但仍可以在另一個終端視窗中看到它,那麼這很方便。

相關內容