從write()調用返回時,核心已經將緩衝區所提供的資料到核心的緩衝區,但是無法保證資料已經寫出到其預定的目的地。的確,寫入調用返回的速度實在太快了,可能沒有時間完成該項目的工作。處理器和硬碟之間的效能差異使得此類令人頭痛的行為顯而易見。
事實上,如果使用者空間應用程式發出write()系統調用,Linux核心會先進行若干檢查,接著將資料複製進緩衝區。稍後,核心會在後台收集所有“髒”(有資料寫入)緩衝區(內容跟相應磁碟塊不同的所有緩衝區),將它們安排成最佳順序,接著寫進磁碟。這讓寫入調用的執行快如閃電,幾乎立即返回,這也讓核心可以將寫入操作延後到較閒置時段再進行,並且是多筆寫入操作會整批一起進行。
延後進行的寫入操作並不會改變POSIX的語義。舉例來說,資料剛寫入緩衝區而尚未寫回磁碟,此時如果發出讀取請求,此請求可從緩衝區得到滿足,而且不會因此而讀取到地盤上的舊資料。此行為會實際提高效能,因為讀取請求可從記憶體中的緩衝區得到滿足,而不必從磁碟。當讀取和寫入請求如預期般交替出現時,結果也和預期一樣,也就是說,資料被寫回磁碟之前系統不會崩潰!即使應用程式相信寫入請求已經成功完成了,但事實上資料尚未寫回磁碟。
延後寫入的另一個問題是無法安排寫入順序,儘管應用程式可能會安排寫入請求的順序,好讓他們能夠按照特定的順序寫回磁碟,核心會以它認為合適的方式重新安排寫入請求的順序,主要是基於新能的考慮。除非系統崩潰,否則這通常不是一個問題,因為所有緩衝區最後都會寫回磁碟,所以一切都很好。即使如此,絕大多數的應用程式實際上並不關心寫入請求的順序。
延遲寫入必須探討的最後一個問題是彙報I/O錯誤。寫回磁碟期間可能會發生任何無法向發出寫入請求的進程彙報的I/O錯誤,例如磁碟機故障。的確,緩衝區與這些進程毫無關係。假如有多個進程“弄髒”(將資料寫入)單一緩衝區,而這些進程可能在資料寫入緩衝區之後並且在資料寫回磁碟之前先借宿了。
核心會試圖盡量降低延後寫入的風險,為了確保資料可以被及時寫出,核心未緩衝區設立了一個時間上限,而且會在時間超過上限之前寫出所有“髒”緩衝區。使用者可通過/proc/sys/vm/dirty_expire_centiseconds來設定此值,此值以厘秒(百分之一秒)為單位。