デバイスの先頭をランダムなビットまたはゼロで上書きするにはどうすればよいですか?

デバイスの先頭をランダムなビットまたはゼロで上書きするにはどうすればよいですか?

デバイスの小さな部分をゼロまたは任意のビットで覆いたいだけです。より正確には、すべてのセクターの最初の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バイト)を意味できます)。この場合、次のことができます。ksh93headhead

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/urandom1回の読み取りで32MiBから1バイトのデータを引いたものを得ることはできません(したがって、1MiBの場合はまだ問題ありませんが、別のバージョンのLinux用YMMVを使用している場合)。 、そして の場合には/dev/random数バイト(現在のエントロピープールにあるバイト)だけがあります。 GNU実装には、要求バッファがいっぱいになるまで読み続ける動作がddありますが、GNUがない場合、唯一のオプションは一度に1バイトの読み取りを実行することです。これはパフォーマンスに大きな影響を与えます。iflag=fullblockheaddd
  • パフォーマンス:少量のデータ(数百メガバイト未満)(データが後でディスクにフラッシュまたは書き込まれるバッファに書き込まれる場合)以外の場合、/dev/nullプロセスはI / Oバインドされます。読み取り/dev/urandomまたは/dev/randomボトルネックが発生すると、乱数生成またはディスクI / Oが発生します。この場合、ddとheadの間に大きな違いはありません。いずれにせよ、headCPUオーバーヘッドが高い可能性があります(パフォーマンスがI / Oバインドされている場合は不明)。

    • head基本的なツールです。実装は、すべてのタイプの入力と出力に対して依然として信頼性が高く、あまりにも多くのリソースを使用せずに、できるだけ効率的にタスクを実行しようとします。同じ読み取り+書き込みループを実行しますdd。パフォーマンスの主な違いは読み取りと書き込みのサイズであり、それによって実行されるシステムコールの数が決まります。

      これらのサイズはシステムの実装とバージョンによって異なり、headシステムによって異なります。マイシステムで最新バージョンのGNUを使用している場合、head読み取りサイズはBUFSIZE(GNUシステムでは8KiB)、書き込みサイズは4KiBですが変更できますstdbuf -o 1M

      ksh93組み込みhead関数は64KiBの読み書きを行い、少なくとも私のシステムではlibcのstdioを使用していないようです。

      GNUのheadstdioの使用は、stdioが追加のオーバーヘッドを引き起こすことを意味します(実装はシステムによって異なります)。

      現在のバージョンのGNUは、キャッシュがそれに応じて最適化されるようにデータを順次読み取ることをシステムに通知するcatために使用されます。fadvise一部の実装がheadこれを行うことができるか、将来的にも実行できることは不可能ではありません。低レベルなので、ユーザーが指示した場合にのみ実行したいと思います(これらのサポートがある実装ddはわかりません)。dd

    • ddread()非常に低いレベルで直接呼び出しとwrite()システム呼び出しを実行します。 Linuxなどの特別なAPIを使用する以外に、これよりはるかに効率的ではありませんsendfile()

      read()これにより、合計サイズをより適切に制御できるwrite()ため、入力/出力タイプと利用可能なリソースに基づいて最適化できます。たとえば、空きメモリが多い場合は、一度にデータ全体を読み取る方が良いでしょう。 (私がテストした結果、/dev/zeroから/devにコピーしたときに比べて大幅に改善された点は見られませんでした。/null)サイズは32KiBであり、ブロックサイズが1MiB以降でも性能が低下し始めます。

  • 移植性

    -c、、、bs=10Mconv=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,synchead

代替。

  • pv -Ss 10M < /dev/zero > /dev/sdax10Mをコピーして進行状況バーを表示します。テストでは、デフォルトの読み取り/書き込みサイズは128KiBでした。 options を使用してこれを変更できますが、-B私のテストでは128KiBが最良の結果を提供しました。 sと同じオプションがpvあります。-Eddconv=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
    

perl10000MiBを書くことは、繰り返し読み取りソリューションよりも効率的です(オーバーヘッドにもかかわらず)/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データを提供する他のファイルを使用することもできます。このコマンドは、出力ファイル/デバイスの先頭からデータの書き込みを開始します。

関連情報