Вопрос или проблема
Я ищу способ фрагментировать существующий файл, чтобы оценить производительность некоторых инструментов. Я нашел решение для файловой системы NTFS под названием MyFragmenter, как описано в этой теме. Однако я не могу найти ничего для ext2/3/4… Я полагаю, могу разработать свой собственный фрагментатор файлов, но из-за нехватки времени хотел бы найти более быстрое решение. Я нашел несколько инструментов, таких как HJ-Split, который разбивает файл на меньшие части, но я сомневаюсь, что это имитирует фрагментацию файла.
Существует ли какое-либо решение для моей проблемы?
Если вы хотите обеспечить фрагментацию, но не предотвращать её (так что у вас лишь частичный контроль над тем, что происходит), и вам не важны детали фрагментации, вот быстрый и грязный способ сделать это.
Чтобы создать файл из n
блоков как минимум в двух фрагментах:
- Откройте файл с синхронными записями, запишите m < n блоков.
- Откройте другой файл. Добавляйте в него, пока на диске не останется не более n – m свободных блоков. Не делайте его разреженным по ошибке!
- Запишите оставшиеся n – m блоков в первый файл.
- Закройте и
unlink
второй файл.
Вы можете фрагментировать на большее количество частей, чередуя больше файлов.
Это предполагает, что файловая система доступна для такого рода пыток, т.е. не в много пользовательской или критически важной для миссии среде. Это также предполагает, что в файловой системе нет зарезервированных блоков, или зарезервированные блоки зарезервированы для вашего UID, или вы являетесь root.
Нет прямого способа гарантировать фрагментацию, потому что системы Unix используют абстракцию файловой системы, так что вы никогда не общаетесь с необработанной файловой системой.
Кроме того, обеспечение фрагментации на уровне файловой системы ничего не говорит о том, что происходит на более низких уровнях. LVM, программные и аппаратные RAID, перенастройка секторов на аппаратном уровне и другие уровни абстракции могут нарушить ваши ожидания (и измерения).
Мне еще не встречалась универсальная файловая система в 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; # неопределенное поведение
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 ГБ определенно фрагментируется.)
Система виртуальной памяти, вероятно, кэширует и откладывает/переставляет слишком маленькие записи. Вот почему торрент-клиенты удаются фрагментировать (так как они обычно не загружают со скоростью >10MB/s), но мой скрипт не. Я думаю, его можно настроить, снизив пороги vm. Посмотрите /proc/sys/vm/dirty_*
Я случайно столкнулся с ситуацией, когда нужно создать фрагментированный файл в Linux ext4. Я сделал это, вызвав fallocate, который можно использовать для создания «дырок» в файле, это перерабатывает дыры в используемое дисковое пространство, тем самым вызывая фрагменты. См. здесь скрипт для генерации фрагментированного файла (и история прилагается). Таким образом, легко создать тысячи фрагментов (или экстентов).
Без внешних приложений есть неплохой способ:
dd if=/dev/zero of=file1 bs=4096 count=1000000 &
dd if=/dev/zero of=file2 bs=4096 count=1000000 &
Запустите их из скрипта (или скопируйте и вставьте), чтобы они начали (почти) одновременно. Поскольку они соревнуются за дисковое пространство для хранения своих выходных файлов, они будут переплетаться и создавать фрагментированные файлы.
Используйте filefrag file?
, чтобы проверить, действительно ли выходные файлы (file1
и file2
) были фрагментированы, так как нет никакой гарантии (это зависит от множества факторов, таких как тип файловой системы, заполненность диска и т.д.).
Также поэкспериментируйте с различными значениями для параметров bs
и count
.
Ответ или решение
Как умышленно фрагментировать файл в файловых системах Linux (ext2/ext3/ext4)
Если вы хотите протестировать производительность инструментов, важно знать, как создавать фрагментированные файлы на файловых системах Linux. В отличие от NTFS, в файловых системах ext2, ext3 и ext4 нет прямых инструментов для создания фрагментации файлов. Однако существуют различные способы добиться этого. В данной статье я представлю несколько методов, которые могут помочь вам в достижении ваших целей.
Метод 1: Использование нескольких файлов
Этот метод основан на создании двух или более файлов, которые будут записываться параллельно, что приведет к фрагментации целевого файла.
- Создайте первый файл и откройте его для записи.
- Создайте второй файл и записывайте в него данные, пока на диске не останется свободного места. Убедитесь, что не создается разреженный файл.
- Затем завершите запись в первый файл, используя оставшееся место.
- Закройте оба файла и удалите второй файл.
Этот метод показывает, как можно вызвать фрагментацию, записывая данные не последовательно на диск.
Метод 2: Скрипт на Perl для случайного фрагментирования
Вы можете написать простую программу на 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; # Установите размер файла
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;
Этот скрипт создаст фрагментированный файл, если используется файловая система, позволяющая фрагментацию.
Метод 3: Использование fallocate
Команда fallocate
также может помочь в создании фрагментированных файлов за счет «прокалывания» дырок в существующем файле. Это пример команды:
fallocate -p -l 1G myfile
Эта команда создаст файл размером 1G с фрагментами.
Проверка фрагментации
После создания фрагментированного файла вы можете использовать команду filefrag
, чтобы проверить фрагментацию:
filefrag myfragmentedfile
Это покажет количество фрагментов (или эксентов) в файле и поможет вам определить степень его фрагментации.
Заключение
Создание фрагментированных файлов в Linux может быть выполнено несколькими способами. Описанные методы обеспечивают контроль над процессом фрагментации и позволяют оценить производительность тестируемых инструментов. Помните, что фактический эффект фрагментации может варьироваться в зависимости от используемой файловой системы и состояния диска.
Не стесняйтесь экспериментировать с различными параметрами в целях достижения нужного результата.