dd
如何用於右移數據塊?
以一個 100MB 的原始塊設備為例。即 204800 個塊,每個塊 512 個字節,總共 102760448 個字節。
挑戰在於移動前 98MB(200704 個塊),使其前面有 2MB(4096 個塊)的間隙。要就地執行此操作,需要不向尚未讀取的扇區寫入任何內容。實現此目的的一種方法是引入緩衝區:
$ dd if=/dev/sdj2 count=200704 | mbuffer -s 512 -b 4096 -P 100 | dd of=/dev/sdj2 seek=4096
期望
mbuffer
在將任何內容傳遞給寫入器之前將儲存 4096 個塊,從而確保沒有任何內容寫入尚未讀取的區域,並且寫入器比讀取器滯後緩衝區的大小。緩衝區應該允許讀取器和寫入器在這些約束內盡可能快地操作。但是,它似乎不能可靠地工作。我嘗試過使用真實設備,但它從來沒有在它們身上工作過,而對文件的實驗在我的 64 位機器上工作,但在我的 32 位機器上卻不行。
首先,一些準備工作:
$ dd if=/dev/sdj2 count=200704 | md5sum 0f0727f6644dac7a6ec60ea98ffc6da9 $ dd if=/dev/sdj2 count=200704 of=testfile
這不起作用:
$ dd if=/dev/sdj2 count=200704 | mbuffer -s 512 -b 4096 -P 100 -H | dd of=/dev/sdj2 seek=4096 summary: 98.0 MiByte in 4.4sec - average of 22.0 MiB/s md5 hash: 3cbf1ca59a250d19573285458e320ade
這適用於 64 位系統,但不適用於 32 位系統:
$ dd if=testfile count=200704 | mbuffer -s 512 -b 4096 -P 100 -H | dd of=testfile seek=4096 conv=notrunc summary: 98.0 MiByte in 0.9sec - average of 111 MiB/s md5 hash: 0f0727f6644dac7a6ec60ea98ffc6da9
如何可靠地做到這一點?
筆記
我已閱讀有關緩衝的其他問題並查看了
pv
,buffer
和mbuffer
. 我只能讓後者使用所需的緩衝區大小。使用中間儲存是解決這個問題的一個明顯解決方案,它始終有效,但在沒有足夠的備用容量可用時它是不切實際的。
執行 Arch Linux
mbuffer
版本 20140302 的測試平台。
如果沒有緩衝區,您可以一次一個塊地倒退。
for i in $(seq 100 -1 0) do dd if=/dev/thing of=/dev/thing \ bs=1M skip=$i seek=$(($i+2)) count=1 done
請注意,由於缺少錯誤檢查,此範例很危險。
由於
dd
呼叫量,它也很慢。如果你有空閒的記憶體,你可以使用更大的塊大小。使用緩衝區,請注意陷阱。僅保證 100% 預填充是*不夠的。*您需要的是整個過程中的最小填充量。緩衝區永遠不能低於
2M
,否則您將再次覆蓋尚未讀取的數據。因此,雖然理論上您可以不使用任何類型的緩衝區而只使用連結
dd
:dd if=/dev/thing bs=1M | \ dd bs=1M iflag=fullblock | \ dd bs=1M iflag=fullblock | \ dd of=/dev/thing bs=1M seek=2
在實踐中,這並不能可靠地工作,因為不能保證第一個
dd
設法繼續讀取數據,而最後一個dd
(中間2M
有“緩衝區”)已經在寫入。您可以通過使中間緩衝區顯著增大來大大增加您的機會,但即便如此,它也不可靠。
不幸的是,我不知道一個具有最小填充屬性的好的緩衝程序。只要緩衝區內的安全裕度小於您的安全裕度,您就需要停止輸出。