web-dev-qa-db-ja.com

ddはいつデータをコピーするのに適していますか? (または、read()およびwrite()が部分的である場合)

短いバージョン:データのコピーにdd安全に使用できるのはどのような場合ですか?部分的な読み取りまたは書き込み?

Long version — preamble:ddは、特にデバイスとの間でデータをコピーするためによく使用されます( =)。これは、他のツールよりも低いレベルでデバイスにアクセスできるという神秘的なプロパティに起因する場合があります(実際には、魔法をかけているのはデバイスファイルです)—しかし、dd if=/dev/sdacat /dev/sdaと同じです。 ddの方が速いと思われることもありますが、実際には catの方が優れています 。それにもかかわらず、 ddには固有のプロパティがあり、時々本当の意味で役立つ

問題:dd if=foo of=barは実際にはcat <foo >barと同じではありません。ほとんどのユニスでは、ddread() を1回呼び出します。 (ddの「入力ブロックの読み取り」を構成するものについて [〜#〜] posix [〜#〜] ファジーを見つけます。)read()が部分的な結果(POSIXおよびその他の参照ドキュメントによれば、実装のドキュメントに別の指示がない限り許可されます)、部分的なブロックがコピーされます。まったく同じ問題がwrite()にも存在します。

観察:実際には、ddがブロックデバイスと通常のファイルに対応できることがわかりましたが、それはあまり運動していません。パイプに関しては、ddに問題があることは難しくありません。たとえば、試してみてください このコード

yes | dd of=out bs=1024k count=10

outファイルのサイズを確認します(おそらく10MB未満です)。

質問:データのコピーにddを使用しても安全なのはどのような場合ですか?言い換えると、ddがすべてのデータを確実にコピーできるようにするには、ブロックサイズ、実装、ファイルタイプなどのどの条件を使用できますか?

GNU dd には、ループ内でread()またはwrite()を呼び出してブロック全体を転送するように指示するfullblockフラグがあります。したがって、dd iflag=fullblockは常に安全です。私の質問は、これらのフラグ(他の実装には存在しない)が使用されない場合についてです。

¹ OpenBSD、GNU coreutilsおよびBusyBoxで確認しました。

ソケット、パイプ、またはttyを使用すると、read()およびwrite()は要求されたサイズ未満で転送できるため、これらでddを使用する場合は、fullblockフラグが必要です。ただし、通常のファイルとブロックデバイスでは、短い読み取り/書き込みを実行できるのは、EOFに達したとき、またはエラーが発生したときの2回だけです。これが、fullblockフラグのない古いddの実装がディスク複製に安全に使用できる理由です。

6
psusi