如何故意对文件进行碎片化

如何故意对文件进行碎片化

我正在寻找一种对现有文件进行分段的方法,以便评估某些工具的性能。我找到了一个名为 NTFS 文件系统的解决方案我的碎片器如本文所述线。但是我找不到 ext2/3/4 的任何内容...我想我可以开发自己的文件碎片器,但由于时间限制,我想找到更快的解决方案。我找到了一些工具,例如HJ-分裂它将文件分割成更小的部分,但我怀疑这会模拟文件碎片。

他们可以解决我的问题吗?

答案1

如果你想确保碎片但不防止它(所以你只能部分控制发生的事情),并且你不关心碎片的细节,这是一种快速而肮脏的做事方式。

要创建n至少包含两个片段的块文件:

  1. 使用同步写入打开文件,写入 m < n 块。
  2. 打开另一个文件。添加到它,直到磁盘上最多有 n - m 块可用。不要错误地将其稀疏!
  3. 将剩余的 n - m 块写入第一个文件。
  4. 关闭unlink第二个文件。

您可以通过交错更多文件来分割更多片段。

这假设文件系统可用于此类折磨,即不在多用户或关键任务环境中。它还假设文件系统没有保留块,或者保留块是为您的 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 包中包含的命令检查碎片。

以下是 torrent 的作用示例:

# 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/s 的速度下载),但我的脚本却不会。我认为可以通过降低虚拟机阈值来调整。看/proc/sys/vm/dirty_*

答案3

我偶然发现一个情况,需要在Linux ext4中生成碎片文件。我是通过调用这样做的错误定位,可用于在给定文件上打孔,这会将孔回收到可用磁盘空间,从而导致碎片。看这里用于生成碎片文件(以及附加的故事)的脚本。通过这种方式,可以轻松创建数千个片段(或范围)。

相关内容