ショートバージョン: dd
はどのような状況ですか データのコピーに安全に使用できます。安全とは、部分的な読み取りまたは書き込みによる破損のリスクがないことを意味しますか?
長いバージョン—前文: dd
特にデバイスとの間でデータをコピーするためによく使用されます(例)。他のツールよりも低いレベルでデバイスにアクセスできるという神秘的な特性が原因である場合があります(実際には、魔法を実行しているのはデバイスファイルです)が、 dd if =/ dev / sda
cat / dev / sda
と同じです 。 dd
速いと思われることもありますが、 cat
実際にそれを打ち負かすことができます。それでも、 dd
独自の特性を備えているため、真に役立つ場合があります。
問題: dd if =foo of =bar
実際、 cat
と同じではありません 。ほとんどのユニス¹では、 dd
read()
を1回呼び出します 。 (POSIXは、 dd
の「入力ブロックの読み取り」を構成するものについてあいまいだと思います。 。) read()
の場合 部分的な結果を返します(POSIXおよびその他の参照ドキュメントによると、実装ドキュメントで特に明記されていない限り、これは許可されています)、部分的なブロックがコピーされます。 write()
にもまったく同じ問題が存在します 。
観察 :実際には、 dd
ブロックデバイスや通常のファイルに対応できますが、それは私があまり行使していないということかもしれません。パイプに関しては、 dd
を配置するのは難しくありません 故障して;たとえば、次のコードを試してください:
yes | dd of=out bs=1024k count=10
out
のサイズを確認します ファイル(10MBをはるかに下回る可能性があります)。
質問 :どのような状況で dd
データのコピーに安全に使用できますか?つまり、ブロックサイズ、実装、ファイルタイプなどの条件によって、 dd
が確実になります。 すべてのデータをコピーしますか?
(GNUDdにはfullblock
があります read()
を呼び出すように指示するフラグ またはwrite()
完全なブロックを転送するためにループで。したがって、 dd iflag =fullblock
常に安全です。私の質問は、これらのフラグ(他の実装には存在しない)が使用されていない場合についてです。)
¹
OpenBSD、GNU coreutils、BusyBoxをチェックしました。
承認された回答:
仕様から:
-
bs =
の場合expr
オペランドが指定されており、sync
以外の変換はありません 、noerror
、またはnotrunc
要求された場合、各入力ブロックから返されるデータは、個別の出力ブロックとして書き込まれます。read()
の場合 フルブロック未満を返し、sync
変換が指定されていない場合、結果の出力ブロックは入力ブロックと同じサイズになります。
だから、これはおそらくあなたの混乱を引き起こすものです。はい、 dd
設計 ブロッキングの場合、デフォルトでは部分的な read()
sは部分的なwrite()
に1:1でマッピングされます s、または sync
bs =
へのテールパディングNULまたはスペース文字を削除します conv =sync
の場合のサイズ が指定されています。
これは、 dd
を意味します データのコピーに安全に使用できます(部分的な読み取りまたは書き込みによる破損のリスクはありません) count =
によって任意に制限されている場合を除くすべての場合 それ以外の場合はdd
であるため、引数 喜んでwrite()
入力がread()
であったものと同じサイズのブロックでの出力 read()
になるまで sそれを完全に通過します。そして、この警告でさえ唯一の真実 bs =
の場合 指定またはobs=
ではありません 仕様の次の文として指定されています:
-
bs =
の場合expr
オペランドが指定されていないか、sync
以外の変換 、noerror
、またはnotrunc
要求された場合、入力は処理され、フルサイズの出力ブロックに収集されます 入力の終わりに達するまで。
ibs =
なし および/またはobs=
引数これは重要ではありません– ibs
およびobs
デフォルトでは両方とも同じサイズです。ただし、明示的になることができます 異なるサイズを指定して入力バッファリングについて どちらの場合でも bs =
を指定する (優先されるため) 。
たとえば、次の場合:
IN| dd ibs=1| OUT
…次に、POSIX dd
write()
収集による512バイトのチャンク 単独でread()
バイトを単一の出力ブロックに。
それ以外の場合は…
IN| dd obs=1kx1k| OUT
…POSIXdd
read()
最大 一度に512バイト、ただし write()
すべてのメガバイトサイズの出力ブロック(カーネルはおそらく最後のものを許可および除外します-それはEOFであるため) フルサイズの出力ブロックに入力を収集することにより、完全に 。
ただし、仕様からも:
-
count =n
- コピーのみn 入力ブロック。
count =
i?bs =
にマップします ブロックなど、 count =
の任意の制限を処理するため 移植には、2つの dd
が必要です s。 2つのdd
でそれを行う最も実用的な方法 sは、ある出力を別の入力にパイプ処理することにより、特別なファイルの読み取り/書き込みの領域に確実に配置されます。 元の入力タイプに関係なく。
IPCパイプとは、 [io] bs =
を指定する場合を意味します 安全に行うには、そのような値をシステムで定義された PIPE_BUF
内に保持する必要があるという引数 制限。 POSIXは、システムカーネルはアトミックな read()
のみを保証する必要があると述べています sおよびwrite()
■PIPE_BUF
の制限内 Limits.h
で定義されているとおり 。 POSIXは、 PIPE_BUF
を保証します 少なくとも …
-
{_ POSIX_PIPE_BUF}
- パイプへの書き込み時にアトミックであることが保証されている最大バイト数。
- 値:512
…(これはデフォルトの dd
でもあります i / oブロックサイズ) 、ただし、実際の値は通常少なくとも4kです。最新のLinuxシステムでは、デフォルトで64kです。
したがって、 dd
を設定するとき ブロックファクターで実行する必要があるプロセス 3つの値に基づく:
- bs =(obs =
PIPE_BUF
以下) - n=必要な合計バイト数
- count =n / bs
いいね:
yes | dd obs=1k | dd bs=1k count=10k of=/dev/null
10240+0 records in
10240+0 records out
10485760 bytes (10 MB) copied, 0.1143 s, 91.7 MB/s
dd
を使用してi/oを同期する必要があります シークできない入力を処理します。言い換えると、パイプバッファを明示的にすると、問題がなくなります。それがdd
です。ここでの不明な数量はdd
の数量 次に、少し情報に基づいた乗算で dd
を作成できます データのコピーに安全に使用できます(部分的な読み取りまたは書き込みによる破損のリスクはありません) count =
で入力を任意に制限する場合でも 任意のPOSIXシステムで任意の入力タイプを使用し、1バイトを失うことはありません。
POSIX仕様の抜粋は次のとおりです。
-
ibs =
expr
- 入力ブロックサイズをバイト単位で
expr
で指定します (デフォルトは512) 。
- 入力ブロックサイズをバイト単位で
-
obs =
expr
- 出力ブロックサイズをバイト単位で
expr
で指定します (デフォルトは512) 。
- 出力ブロックサイズをバイト単位で
-
bs =
expr
- 入力ブロックサイズと出力ブロックサイズの両方を
expr
に設定します バイト、ibs =
に取って代わります およびobs=
。sync
以外の変換がない場合 、noerror
、およびnotrunc
が指定されている場合、各入力ブロックは、短いブロックを集約せずに単一のブロックとして出力にコピーされます。
- 入力ブロックサイズと出力ブロックサイズの両方を
ここでは、この説明の一部についても詳しく説明しています。