
答え1
あなたがしたい場合は確保する断片化ではなく防ぐ(つまり、何が起こるかについて部分的な制御しかできない)断片化の詳細を気にしない場合は、ここで手っ取り早く簡単な方法を紹介します。
n
少なくとも 2 つのフラグメントでブロックのファイルを作成するには:
- 同期書き込みでファイルを開き、m < n ブロックを書き込みます。
- 別のファイルを開きます。ディスク上の空きブロックが最大で n - m ブロックになるまで追加します。誤ってスパースにしないでください。
- 残りの n - m ブロックを最初のファイルに書き込みます。
unlink
2番目のファイルを閉じます。
より多くのファイルをインターレースすることで、より多くの部分に断片化できます。
これは、ファイルシステムがこの種の拷問に使用できることを前提としています。つまり、マルチユーザーまたはミッションクリティカルな環境ではありません。また、ファイルシステムに予約ブロックがないか、予約ブロックが UID または root 用に予約されていることを前提としています。
ありません直接Unix システムはファイルシステムの抽象化を採用しているため、生のファイルシステムと通信することはなく、断片化を確実に行う方法ではありません。
また、ファイルシステム レベルの断片化を確認しても、下位レベルで何が起きるかはわかりません。LVM、ソフトウェアおよびハードウェア RAID、ハードウェア レベルのセクター再マッピング、その他の抽象化レイヤーは、期待値 (および測定値) を台無しにする可能性があります。
答え2
Linux 上で、連続したファイルよりも書き込みスループットを犠牲にする汎用ファイル システムに出会ったことはありません。つまり、特にスパース ファイルの場合、断片が非連続的な順序で書き込まれると、すべてのファイル システムが断片化します。
簡単な方法: ファイルを Torrent クライアントで実行します。できれば、ファイルを事前に割り当てないクライアントがよいでしょう。BitTornado または rtorrent が適しています。(前者には設定可能な割り当てモードがあります)
難しい方法: ソース ファイルを数 KB のサイズに分割し、シャッフルします。宛先ファイルを開きます。各部分について、正しい位置を探して書き込みます。
これを実行する Perl スクリプトは次のとおりです。
#!/usr/bin/perl
use List::Util qw/shuffle/;
use IO::Handle;
use constant BLOCK_SIZE => 4096;
my ($src, $dst) = @ARGV;
my $size = (stat($src))[7];
my @blocks = shuffle(0 .. ($size / BLOCK_SIZE));
my ($srcfh, $dstfh);
open $srcfh, "<", $src or die "cannot open $src: $!";
open $dstfh, ">", $dst or die "cannot open $dst: $!";
truncate $dstfh, $size; # undefined behaviour
my $buf;
for my $blockno (@blocks) {
seek $_, $blockno * BLOCK_SIZE, 0 for ($srcfh, $dstfh);
read $srcfh, $buf, BLOCK_SIZE;
print $dstfh $buf;
$dstfh->flush;
}
close $dstfh;
close $srcfh;
filefrag
e2fsprogs パッケージに含まれるコマンドを使用して断片化をチェックできます。
トレントが行うことの例を次に示します。
# ls -sh amd64memstick-5.1.2.fs.gz
239M amd64memstick-5.1.2.fs.gz
# filefrag amd64memstick-5.1.2.fs.gz
amd64memstick-5.1.2.fs.gz: 585 extents found
私のスクリプトで得られた結果は次のとおりです (ext3 上):
$ ls -sh source.tar
42M source.tar
$ perl fragment.pl source.tar fragmented.tar
$ md5sum fragmented.tar source.tar
f77fdd7ab526ede434f416f9787fa9b3 fragmented.tar
f77fdd7ab526ede434f416f9787fa9b3 source.tar
# filefrag fragmented.tar
fragmented.tar: 395 extents found
編集:気にしないでください。結局のところ、かなり大きなファイル (1.5 GB のファイル フラグメントは確実) を除いて、それほどうまく機能しないようです。
VM システムはおそらくキャッシュを行っており、小さすぎる書き込みを延期/並べ替えています。これが、Torrent クライアントが断片化 (通常は 10MB/秒を超えるダウンロードは行わないため) する理由ですが、私のスクリプトでは断片化しません。VM しきい値を下げることで調整できると思います。/proc/sys/vm/dirty_*