
デバイスの小さな部分をゼロまたは任意のビットで覆いたいだけです。より正確には、すべてのセクターの最初の1%または数MiBをカバーしたいと思います。これを行う簡単な方法はありますか?
答え1
非常に遅いため、/dev/urandom
大量のデータ(フルディスク)を処理するのには適していませんが、小さな領域には適しています。
8MiBを扱う例:
dd bs=1M count=8 iflag=fullblock if=/dev/urandom of=/dev/destroyme
または、次のものを使用できますshred
。
shred -v -n 1 -s 8M /dev/destroyme
またlosetup
、特定のサイズとオフセットのデバイスを作成し、独自のサイズ/オフセットオプションを持たないユーティリティを使用してそれらを上書きすることもできます。
losetup --find --show --offset 0 --sizelimit $((8*1024*1024)) /dev/destroyme
# will print /dev/loopX
cat /dev/urandom > /dev/loopX
losetup -d /dev/loopX
答え2
他のファイルと同様に、最初の10MiBを0で上書きします。
head -c10M < /dev/zero 1<> /dev/sdax
ブロックデバイスファイルの場合、1<>
切り捨てなしで開く必要さえありません。ブロックデバイスの切り捨てのようなものがないので、次のように簡単に実行できます。
head -c10M < /dev/zero > /dev/sdax
すべてのヘッダー実装がこれをサポートするわけではなく-c
、サポートしている場合、すべてがこのサフィックスをサポートするわけではM
ありません(サポートしている場合は組み込みのようにM
メガバイト(1000000バイト)またはGNUのようにメガバイト(1048576バイト)を意味できます)。この場合、次のことができます。ksh93
head
head
head -c "$((10 * 1024 * 1024)"
確かにしてください。
比較するとdd bs=1M count=10 < /dev/zero > /dev/sdax
:
概念的に
head
ファイルから指定された数のバイトまたは行を読み取り、それをstdoutに書き込むコマンド。- whileは、
dd
必要な方法でデータを読み書きできる低レベルのコマンドです。
head
作業用に設計されたコマンドなので、ここで使用しています。dd
特定のユースケースに合わせて最適化したり、特定の機能の1つを使用したい場合は、dd
これを使用してください(移植性に関する注意事項も参照)。読み取り+書き込みループ:
head -c10M
関係なく、要求されたデータを読み取る試みが行われ、エラーが発生した場合、終了ステータスが0以外の場合にのみ失敗します。dd bs=1M count=10
、10回の読み取りが行われ(エラーがない限り)、一部のデータを返す読み取りごとに読み取ったデータ量を使用して書き込みが行われます。この方法は、各読み取りが要求されたデータ1Mを正確に返す場合にのみ機能します。実際には正しいです/dev/zero
。しかし、Linux(最小4.6)では、/dev/urandom
1回の読み取りで32MiBから1バイトのデータを引いたものを得ることはできません(したがって、1MiBの場合はまだ問題ありませんが、別のバージョンのLinux用YMMVを使用している場合)。 、そして の場合には/dev/random
数バイト(現在のエントロピープールにあるバイト)だけがあります。 GNU実装には、要求バッファがいっぱいになるまで読み続ける動作がdd
ありますが、GNUがない場合、唯一のオプションは一度に1バイトの読み取りを実行することです。これはパフォーマンスに大きな影響を与えます。iflag=fullblock
head
dd
パフォーマンス:少量のデータ(数百メガバイト未満)(データが後でディスクにフラッシュまたは書き込まれるバッファに書き込まれる場合)以外の場合、
/dev/null
プロセスはI / Oバインドされます。読み取り/dev/urandom
または/dev/random
ボトルネックが発生すると、乱数生成またはディスクI / Oが発生します。この場合、ddとheadの間に大きな違いはありません。いずれにせよ、head
CPUオーバーヘッドが高い可能性があります(パフォーマンスがI / Oバインドされている場合は不明)。head
基本的なツールです。実装は、すべてのタイプの入力と出力に対して依然として信頼性が高く、あまりにも多くのリソースを使用せずに、できるだけ効率的にタスクを実行しようとします。同じ読み取り+書き込みループを実行しますdd
。パフォーマンスの主な違いは読み取りと書き込みのサイズであり、それによって実行されるシステムコールの数が決まります。これらのサイズはシステムの実装とバージョンによって異なり、
head
システムによって異なります。マイシステムで最新バージョンのGNUを使用している場合、head
読み取りサイズはBUFSIZE(GNUシステムでは8KiB)、書き込みサイズは4KiBですが変更できますstdbuf -o 1M
。ksh93
組み込みhead
関数は64KiBの読み書きを行い、少なくとも私のシステムではlibcのstdioを使用していないようです。GNUの
head
stdioの使用は、stdioが追加のオーバーヘッドを引き起こすことを意味します(実装はシステムによって異なります)。現在のバージョンのGNUは、キャッシュがそれに応じて最適化されるようにデータを順次読み取ることをシステムに通知する
cat
ために使用されます。fadvise
一部の実装がhead
これを行うことができるか、将来的にも実行できることは不可能ではありません。低レベルなので、ユーザーが指示した場合にのみ実行したいと思います(これらのサポートがある実装dd
はわかりません)。dd
dd
read()
非常に低いレベルで直接呼び出しとwrite()
システム呼び出しを実行します。 Linuxなどの特別なAPIを使用する以外に、これよりはるかに効率的ではありませんsendfile()
。read()
これにより、合計サイズをより適切に制御できるwrite()
ため、入力/出力タイプと利用可能なリソースに基づいて最適化できます。たとえば、空きメモリが多い場合は、一度にデータ全体を読み取る方が良いでしょう。 (私がテストした結果、/dev/zeroから/devにコピーしたときに比べて大幅に改善された点は見られませんでした。/null)サイズは32KiBであり、ブロックサイズが1MiB以降でも性能が低下し始めます。
移植性
-c
、、、bs=10M
はconv=fullblock
移植可能ではありません。ファイルから特定の量のデータを読み取る唯一のPOSIXコマンドですがdd
、これを安定して使用するには(onを除く/dev/zero
)、上記のようにbs=1
パフォーマンスが悪くなります。書き込みエラーの結果。
ブロックデバイスの終わりを過ぎて書き込もうとすると、両方とも
head
すぐに終了します。dd
ディスクに不良セクタがある場合、ディスクへの実際の書き込みは非同期であるため、通常は検出されません。 GNU実装を使用すると、直接dd
書き込みを強制できます。oflag=direct
これは、dd
最初のエラーで停止することを意味します。最初の失敗したセクタの前にできるだけ多くのデータを書き込むには、デフォルトのブロックサイズ512を使用できます。読み取りエラーの結果
/dev/zero、/dev/urandom、または/dev/randomで読み取りエラーが発生しないでください。しかし、より一般的には、最初の読み取りでは、両方とも
head
エラーdd
で終了します。を使用すると、dd
エラーを引き続き使用できますconv=noerror
。この場合、失敗したブロックをゼロで埋めるオプションsync
()を追加できます。これは、その機能用に設計されていないため、これを行うオプションは提供しません。conv=noerror,sync
head
代替。
pv -Ss 10M < /dev/zero > /dev/sdax
10Mをコピーして進行状況バーを表示します。テストでは、デフォルトの読み取り/書き込みサイズは128KiBでした。 options を使用してこれを変更できますが、-B
私のテストでは128KiBが最良の結果を提供しました。 sと同じオプションがpv
あります。-E
dd
conv=noerror,sync
Linuxでは、パフォーマンスを最適化するためにシステムコールを使用するため、パイプを介したI / Oも容易になります
splice()
。システムコールを使用するには、を
sendfile()
使用できますxfs_io
。xfs_io -c 'sendfile -i src 0 10M' dst
src から dst に 10M データを送信します。しかし、それだけ一つ
sendfile()
/dev/zero
そして、/dev/random
またはではシステムコールを使用できません/dev/urandom
。ただし、スパースファイルには使用できます。truncate -s 1T empty-file xfs_io -c 'sendfile -i empty-file 0 10M' /dev/sdax
動作できますが、大容量(数ギガバイト)の場合、これは
sendfile()
システムコールであるため、その分のメモリを割り当てる必要があるため、効率が低下します。理想的には、数ギガバイト以上を実行したいとdd bs=1M
思います。sendfile()
タイムバイト操作を実行できますが、これを実行できるコマンドはありません。入力には
/dev/zero
実際には必要ありません。読む書き込む各ブロックのデータ。結局、それはゼロだけです。を読み取らずにゼロだけのバッファを作成するのは簡単で/dev/zero
、各書き込み間でこれを再利用できます。たとえば、PERLIO=:unix perl -e '$x = pack("x" . 1024*1024); print $x for 1..10000' > /dev/sdax
perl
10000MiBを書くことは、繰り返し読み取りソリューションよりも効率的です(オーバーヘッドにもかかわらず)/dev/zero
。
答え3
あなたは、任意のデータを提供するデバイスを使用してdd
これを行うことができます。/dev/urandom
一例:
dd if=/dev/urandom of=/dev/sdX bs=1M count=100
これにより、100MBのランダムデータが記録されます。
if
入力ファイルですof
出力ファイルですbs=1M
ブロックサイズは1Mbyteです。count
このブロックは何回作成する必要がありますか?
/dev/zero
入力ファイルや/dev/null
データを提供する他のファイルを使用することもできます。このコマンドは、出力ファイル/デバイスの先頭からデータの書き込みを開始します。