banner
amtoaer

晓风残月

叹息似的渺茫,你仍要保存着那真!
github
telegram
email
x
bilibili
steam
nintendo switch

tokio::fs 中 flush 方法與標準庫同名方法的差異

在 Tokio 非同步上下文進行檔案讀寫操作時,一個常用的模組是 tokio::fs,其中包含了標準庫檔案 API 的同名非同步版本。

大多數檔案方法都具有與標準庫同名方法相同的語義,但 flush 方法稍有不同。

tokio::fs 文件開始#

在編寫這篇文章時,Tokio 的最新版本是 1.43.0。點進文件鏈接可以看到該模組的簡單介紹:

image

據文件所言,由於大多數操作系統都不提供非同步的檔案系統 API,tokio::fs 的非同步檔案操作實際上是將一般的同步檔案操作放到了 spawn_blocking 的執行緒池裡執行。

將來可能會切換到例如 io_uring 的非同步檔案系統 API,但至少當前在所有平台上都是使用執行緒池的方式實現的。

文件中 flush 方法的特別說明#

稍微往下拉一拉,我們可以看到這樣的描述:

image

image

文件特別使用 Note 提示用戶,寫入 Tokio File 時使用 flush 很重要,因為對 write 方法的調用會在寫入完成之前返回,必須顯式調用 flush 才會等待寫入完成。

這與標準庫的 File 不同,是由 spawn_blocking 的底層實現導致的。

標準庫的 flush#

為什麼 Tokio 要額外提醒用戶調用 flush,難道標準庫裡沒有 flush 或者不用調 flush 嗎?這就要回過頭來看一下標準庫的文件

image

還真是!由於 File 結構不包含緩衝區,UnixWindows 上的 flush 方法不會做任何操作。換言之,在 99.99% 的平台上使用標準庫的 File 寫入而忘記 flush 不會影響任何程序邏輯。

image

當然,文件裡也做了補充,告訴我們這只是為了幫助理解給出的底層說明,並不具有約束性,後續版本的行為也是可能變化的。

補充說明#

在查閱過程中我找到了一條 Tokio 主要作者 alice 在論壇的回覆,或許可以幫助理解。

A completed write on a tokio::fs::File means that it has been handed off to the threadpool to be written, but that does not necessarily mean that the threadpool has written it yet. Calling flush allows you to wait for that to happen.

It's not possible to change this. The AsyncWrite trait's signature fundamentally forces us to do it this way.

tokio::fs::File 的寫入操作完成意味著它已經被交給執行緒池進行寫入,但這並不一定意味著執行緒池已經完成了寫入。調用 flush 可以讓你等待寫入操作真正完成。

這是無法改變的。AsyncWrite trait 的簽名從根本上迫使我們以這種方式處理。

總結#

拋開細節不談,我們可以得出一個簡單結論:

寫入檔案不 flush 可能有錯,flush 了肯定沒錯!

寫完檔案刷一下緩衝區是個好習慣,可能沒效果,但肯定不會出問題。 😋

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。