Dd

使用 dd 創建隨機數據並獲得“部分讀取警告”。現在警告後的數據真的是隨機的嗎?

  • January 13, 2016

我創建了一個包含隨機數據的 1TB 文件dd if=/dev/urandom of=file bs=1M count=1000000。現在我檢查kill -SIGUSR1 <PID>進度並得到以下資訊:

691581+0 Datensätze ein
691580+0 Datensätze aus
725174190080 Bytes (725 GB) kopiert, 86256,9 s, 8,4 MB/s
800950+1 Datensätze ein
800950+0 Datensätze aus
839856947200 Bytes (840 GB) kopiert, 99429,5 s, 8,4 MB/s
dd: warning: partial read (809620 bytes); suggest iflag=fullblock
803432+1 Datensätze ein
803431+1 Datensätze aus
842459273876 Bytes (842 GB) kopiert, 99791,3 s, 8,4 MB/s

我無法解釋警告。它說什麼?警告後我的文件真的是隨機的還是有問題?+0 或 +1是800950+1 Datensätze ein什麼800950+0 Datensätze aus意思?警告後為+1。是錯誤計數嗎?

摘要:dd是一個難以正確使用的古怪工具。不要使用它,儘管有很多教程告訴你。dd有一種“unix street cred”的感覺——但如果你真正了解你在做什麼,你就會知道你不應該用一根 10 英尺長的桿子來觸摸它。

dd每個塊對系統呼叫進行一次呼叫read(由 的值定義bs)。無法保證read系統呼叫返回與指定緩衝區大小一樣多的數據。這往往適用於正常文件和塊設備,但不適用於管道和某些字元設備。請參閱dd 何時適合複製數據?(或者,何時是 read() 和 write() 部分)以獲取更多資訊。如果read系統呼叫返回少於一個完整塊,則dd傳輸部分塊。它仍然複製指定數量的塊,因此傳輸的總字節數少於請求的字節數。

關於“部分讀取”的警告準確地告訴您:其中一個讀取是部分的,因此dd傳輸了一個不完整的塊。在塊計數中,+1表示一個塊被部分讀取;由於輸出計數為+0,所有塊都被寫為已讀。

這不會影響數據的隨機性:所有dd寫出的字節都是它從中讀取的字節/dev/urandom。但是你得到的字節比預期的要少。

Linux/dev/urandom可容納任意大請求(來源:extract_entropy_userin drivers/char/random.c),因此dd在讀取時通常是安全的。但是,讀取大量數據需要時間。如果程序接收到信號,read系統呼叫會在填充其輸出緩衝區之前返回。這是正常行為,應用程序應該read循環呼叫;dd由於歷史原因,不這樣做(dd的起源不明,但它似乎最初是作為一種訪問磁帶的工具,它有特殊的要求,並且從未被改編為通用工具)。當您檢查進度時,這會向dd程序發送一個中斷讀取的信號。您可以選擇知道多少字節dd將全部複製(確保不要中斷它 - 沒有進度檢查,沒有暫停),或者知道dd到目前為止已經複製了多少字節,在這種情況下,您無法知道它將複製多少字節。

ddGNU coreutils 中的版本(在非嵌入式 Linux 和 Cygwin 上找到)有一個標誌fullblock,告訴在循環dd中呼叫(和同上 for ),因此總是傳輸完整塊。錯誤資訊提示你使用它;您應該始終使用它(在輸入和輸出標誌中),除非在非常特殊的情況下(主要是在訪問磁帶時)——如果您使用它,那就是:通常有更好的解決方案(見下文)。read``write``dd

dd if=/dev/urandom iflag=fullblock oflag=fullblock of=file bs=1M count=1000000

另一種確定dd將要做什麼的可能方法是傳遞塊大小為 1。然後您可以知道從塊計數中複製了多少字節,但我不確定如果read在讀取第一個之前中斷a 會發生什麼字節(這在實踐中不太可能發生,但可能發生)。但是,即使它有效,這也很慢。

使用的一般建議dd不要使用dd. 雖然dd經常被宣傳為訪問設備的低級命令,但實際上並非如此:所有的魔法都發生在設備文件(/dev/…)部分,dd只是一個普通工具,具有很高的誤用可能性導致數據失去. 在大多數情況下,至少在 Linux 上,有一種更簡單、更安全的方法來做你想做的事。

例如,要在文件開頭讀取一定數量的字節,只需呼叫head

head -c 1000000m </dev/urandom >file

我在我的機器上做了一個快速基準測試,並沒有觀察到dd大塊大小和head.

如果您需要在開頭跳過一些字節,請tail輸入head

dd if=input of=output count=C bs=B seek=S
<input tail -c +$((S*B+1)) | head -c $((C*B)) >output

如果您想查看進度,請致電lsof查看文件偏移量。這僅適用於正常文件(範例中的輸出文件),不適用於字元設備。

lsof -a -p 1234 -d 1
cat /proc/1234/fdinfo/1

您可以呼叫pv以獲取進度報告(比dd’s 更好),代價是管道中的附加項目(性能方面,幾乎察覺不到)。

引用自:https://unix.stackexchange.com/questions/121865