想像一下兩個進程,一個讀取器和一個寫入器,透過 ext3 檔案系統上的常規檔案進行通訊。 ReaderIN_MODIFY
對文件有 inotify監視。 Writer 在一次呼叫中將 1000 個位元組寫入檔案write()
。 Reader 取得 inotify 事件,並呼叫fstat
該檔案。讀者看到了什麼?
是否能保證讀者能獲得至少 1000 美元的
st_size
文件賠償?從我的實驗來看,似乎不是。是否能保證Reader實際上可以讀取
read()
1000位元組?
這種情況發生在嚴重 I/O 綁定的盒子上。例如,sar
顯示大約 1 秒的等待時間。在我的例子中,Reader 實際上在呼叫 之前在獲取 inotify 事件後等待 10 秒stat
,並且得到的結果太小。
我所希望的是在文件準備好之前不會傳遞 inotify 事件。我懷疑實際發生的是 inotify 事件write()
在 Writer 中的呼叫期間觸發,並且只要數據恰好準備好,數據實際上就可供系統上的其他進程使用。在這種情況下,10s 的時間是不夠的。
我想我只是在尋找核心是否確實按照我猜測的方式實現 inotify 的確認。另外,是否有任何選擇可能可以改變這種行為?
最後,考慮到這種行為,inotify 的意義何在?無論如何,在收到事件後,您都只能輪詢檔案/目錄,直到資料實際可用。不如一直這樣做,而忘記 inotify。
***編輯**** 好吧,正如經常發生的那樣,我所看到的行為實際上是有道理的,現在我明白了我真正在做什麼。 ^_^
我實際上是在響應文件所在目錄上的 IN_CREATE 事件。
我將更改我的程式碼,以便一旦收到 IN_CREATE 事件,我將訂閱檔案本身的 IN_MODIFY,並且在收到 IN_MODIFY 事件之前我不會真正嘗試讀取檔案。我意識到那裡有一個小窗口,我可能會錯過對文件的寫入,但這對於我的應用程式來說是可以接受的,因為在最壞的情況下,文件將在最大秒數後關閉。
答案1
從我所看到的核心原始碼,inotify 僅在寫入完成後才會啟動(即您的猜測是錯誤的)。觸發通知後,實作系統sys_write
呼叫的函數只會發生兩件事write
:設定一些調度程序參數,並更新檔案描述符上的位置。這段程式碼早在2.6.14。當通知觸發時,檔案已經有了新的大小。
檢查是否有可能出錯的地方:
- 也許讀者收到的是以前寫的舊通知。
- 如果讀者打電話
stat
然後又打電話read
,反之亦然,那麼中間可能會發生一些事情。如果您繼續向文件追加內容,則stat
首先調用可以保證您能夠讀取到那麼遠,但在讀取器調用時可能已經寫入了更多數據read
,即使它尚未收到 inotify 通知。 - 僅僅因為編寫器呼叫
write
並不意味著核心將寫入請求的字元數。很少有情況可以保證原子寫入會達到任意大小。然而,每個write
呼叫都保證是原子的:在某些時候資料還沒有寫入,然後突然n位元組已寫入,其中n是調用的返回值write
。如果您觀察到部分寫入的文件,則表示write
傳回的文件小於其大小參數。
用於調查正在發生的情況的有用工具包括:
strace -tt
- 審計子系統