
Я ищу способ фрагментировать существующий файл, чтобы оценить производительность некоторых инструментов. Я нашел решение для файловой системы NTFS под названиемМойФрагментаторкак описано в этомнить. Однако я не могу найти ничего для ext2/3/4... Я гость Я могу разработать свой собственный фрагментатор файлов, но из-за ограничений по времени я хотел бы найти более быстрое решение. Я нашел некоторые инструменты, такие какHJ-Сплиткоторый разбивает файл на более мелкие части, но я сомневаюсь, что это будет имитировать фрагментацию файла.
Есть ли у них решение моей проблемы?
решение1
Если вы хотитегарантироватьфрагментация, но непредотвращать(так что у вас есть лишь частичный контроль над тем, что происходит), и вас не волнуют подробности фрагментации, вот быстрый и грязный способ сделать это.
Чтобы создать файл n
блоков как минимум из двух фрагментов:
- Откройте файл с синхронной записью, запишите m < n блоков.
- Откройте другой файл. Добавляйте в него, пока на диске не останется не более n - m свободных блоков. Не делайте его разреженным по ошибке!
- Запишите оставшиеся n - m блоков в первый файл.
- Закройте и
unlink
второй файл.
Вы можете фрагментировать на большее количество частей, чередуя больше файлов.
Это предполагает, что файловая система доступна для такого рода пыток, т. е. не в многопользовательской или критически важной среде. Это также предполагает, что файловая система не имеет зарезервированных блоков, или зарезервированные блоки зарезервированы для вашего UID, или вы root.
Нет никакихпрямойспособ обеспечить фрагментацию, поскольку системы Unix используют абстракцию файловой системы, поэтому вы никогда не взаимодействуете с необработанной файловой системой.
Кроме того, обеспечение фрагментации на уровне файловой системы ничего не говорит вам о том, что происходит на более низких уровнях. LVM, программный и аппаратный RAID, перераспределение секторов на аппаратном уровне и другие уровни абстракции могут сыграть с вами злую шутку относительно ваших ожиданий (и измерений).
решение2
Я еще не встречал файловую систему общего назначения на Linux, которая бы жертвовала пропускной способностью записи ради наличия смежных файлов. То есть, любая файловая система фрагментируется, если части записываются в непоследовательном порядке, особенно с разреженными файлами.
Простой способ: запустить файл через торрент-клиент — желательно тот, который не выделяет файл заранее. Для этого подходят BitTornado или rtorrent. (У первого есть настраиваемые режимы выделения)
Сложный способ: Разбить исходный файл на части размером в несколько КБ, перемешать их. Открыть целевой файл. Для каждой части найти ее правильное положение и записать ее.
Вот скрипт 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 ГБ точно).
Система VM, вероятно, кэширует и откладывает/переупорядочивает слишком маленькие записи. Вот почему торрент-клиенты умудряются фрагментировать (так как они обычно не загружают со скоростью >10 МБ/с), а мой скрипт — нет. Я думаю, что это можно подправить, снизив пороги VM. Смотрите/proc/sys/vm/dirty_*
решение3
Я случайно наткнулся на ситуацию, когда нужно было создать фрагментированный файл в Linux ext4. Я сделал это, вызвавфаллокировать, который может быть использован для проделывания отверстий в файле, это вернет отверстие в пригодное для использования дисковое пространство, что приведет к фрагментации. Смотритездесьдля скрипта, чтобы сгенерировать фрагментированный файл (и прикрепленную историю). Таким образом, можно легко создать тысячи фрагментов (или экстентов).