Linux
塊設備記憶體與文件系統
塊設備提供緩衝。這意味著
write()
在核心將數據寫入設備之前,塊設備上可以返回成功。程序可以通過呼叫來等待所有緩衝的寫入fsync()
。我已經使用
dd
(或cat
)將文件系統映像寫入設備。這些命令預設不呼叫fsync()
。接下來,假設我要將
mount
寫入的塊設備作為文件系統。我認為
sync
在安裝它之前使用該命令是最安全的。但是如果我不同步塊設備怎麼辦?文件系統是否有可能嘗試讀取一些尚未寫入設備的塊?那麼它可以讀取設備的舊內容,而不是文件系統映像中的正確數據嗎?我的主要興趣是 Linux 行為。(而且 StackExchange 鼓勵我提出一個具體問題。不過,我也可以對任何替代或歷史行為表示贊同 :-)。
當程序關閉塊設備文件時,Linux 會刷新相關的記憶體,迫使程序等待。然而,這只適用於最後一個
close()
。如果其他東西仍然打開塊設備,則不會發生這種情況。包括同一塊設備的任何分區是否仍然打開。所以在一般情況下,最好以某種方式同步設備。
為了安全起見,您應該同步設備的方式是
dd
使用選項執行您的命令conv=fsync
。沒有這個,核心將不會返回寫入錯誤。dmesg
因此,如果您查看核心日誌 ( ) ,您只會注意到一個錯誤。除了等待所有記憶體的寫入之外,最後一個
close()
還丟棄所有記憶體 (kill_bdev()
)。通過查看命令的輸出,我已經為自己驗證了這一點free
。linux-4.20/fs/block_dev.c:1778
static void __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part) { struct gendisk *disk = bdev->bd_disk; struct block_device *victim = NULL; mutex_lock_nested(&bdev->bd_mutex, for_part); if (for_part) bdev->bd_part_count--; if (!--bdev->bd_openers) { WARN_ON_ONCE(bdev->bd_holders); sync_blockdev(bdev); kill_bdev(bdev);
如果您不熟悉 C 程式碼,上面的最後一個塊相當於:
bdev->bd_openers = bdev->bd_openers - 1; if (bdev->bd_openers == 0) { WARN_ON_ONCE(bdev->bd_holders); sync_blockdev(bdev); kill_bdev(bdev);