Ответ 1
dd
- хорошее решение, но для этой цели оно медленное. В Linux у нас есть fallocate
.
Например:
fallocate -l 10G gentoo_root.img
Как я могу быстро создать большой файл в Linux (Red Hat Linux)? dd выполнит задание, но чтение с /dev/zero
и запись на диск могут занять много времени, когда вам нужен файл несколько сотен от размера GB для тестирования... Если вам нужно сделать это многократно, время действительно добавляется.
Мне не важно содержимое файла, я просто хочу, чтобы он был создан быстро. Как это можно сделать?
Использование разреженного файла для этого не будет работать. Мне нужно, чтобы файл был выделен дисковым пространством.
dd
- хорошее решение, но для этой цели оно медленное. В Linux у нас есть fallocate
.
Например:
fallocate -l 10G gentoo_root.img
Это общий вопрос, особенно в сегодняшней среде виртуальных сред. К сожалению, ответ не так прямолинейный, как можно было бы предположить.
dd - очевидный первый выбор, но dd по существу является копией и заставляет вас писать каждый блок данных (таким образом, инициализируя содержимое файла)... И эта инициализация - это то, что занимает столько времени ввода-вывода, (Хотите сделать это еще дольше? Используйте /dev/random вместо /dev/zero! Тогда вы будете использовать процессор, а также время ввода-вывода!) В конце концов, dd - это плохой выбор (хотя по существу это значение по умолчанию, используемое виртуальными машинами для создания "GUI" ). Например:
dd if=/dev/zero of=./gentoo_root.img bs=4k iflag=fullblock,count_bytes count=10G
truncate - еще один выбор - и, скорее всего, самый быстрый... Но это потому, что он создает "разреженный файл". По сути, разреженный файл представляет собой раздел диска с множеством одинаковых данных, а базовая файловая система "обманывает", не сохраняя все данные, а просто "притворяясь", что все это есть. Таким образом, когда вы используете truncate для создания 20-дюймового накопителя GB для вашей виртуальной машины, файловая система фактически не выделяет 20 фунтов стерлингов, но она обманывает и говорит, что там есть 20 нулей GB, хотя хоть один трек на диске может фактически (действительно) использоваться. Например:.
truncate -s 10G gentoo_root.img
fallocate - это final - и лучший - выбор для использования с распределением диска VM, поскольку он по существу "резервирует" (или "выделяет" все пространство, которое вы ищете, но он ничего не удосуживается написать. Итак, когда вы используете fallocate для создания виртуального дискового пространства на 20 и более, вы действительно получаете 20-дюймовый GB файл (а не "редкий файл", и вам не надо было ничего писать, что означает, что практически все может быть там - вроде как новый диск!) Например:
fallocate -l 10G gentoo_root.img
xfs_mkfile 10240m 10Gigfile
fallocate -l 10G 10Gigfile
mkfile 10240m 10Gigfile
prealloc 10Gigfile 10737418240
Попробуйте mkfile <size>
myfile в качестве альтернативы dd
. С опцией -n
размер отмечен, но блоки диска не выделяются до тех пор, пока на них не будут записаны данные. Без опции -n
пробел заполняется нулем, что означает запись на диск, что означает время.
mkfile происходит от SunOS и недоступен везде. Большинство систем Linux имеют xfs_mkfile
, которые работают точно так же, а не только на файловых системах XFS, несмотря на название. Он включается в xfsprogs (для Debian/Ubuntu) или аналогичных пакетов.
В большинстве систем Linux также есть fallocate
, который работает только в определенных файловых системах (таких как btrfs, ext4, ocfs2 и xfs), но является самым быстрым, поскольку он выделяет все пространство (создает непустые файлы), но не инициализирует его.
truncate -s 10M output.file
мгновенно создаст 10 М файл (M означает 1024 * 1024 байта, МБ - 1000 * 1000 - то же самое с K, KB, G, GB...)
EDIT:, как многие указали, это физически не будет выделять файл на вашем устройстве. При этом вы могли бы создать произвольный большой файл, независимо от доступного места на устройстве
Таким образом, при этом вы будете откладывать физическое выделение до тех пор, пока файл не будет доступен. Если вы сопоставляете этот файл с памятью, у вас может не быть ожидаемой производительности.
Но это еще полезная команда знать
Где искать - размер файла, который вы хотите в байтах - 1.
dd if=/dev/zero of=filename bs=1 count=1 seek=1048575
Примеры, где поиск - это размер файла, который вы хотите в байтах
#kilobytes
dd if=/dev/zero of=filename bs=1 count=0 seek=200K
#megabytes
dd if=/dev/zero of=filename bs=1 count=0 seek=200M
#gigabytes
dd if=/dev/zero of=filename bs=1 count=0 seek=200G
#terabytes
dd if=/dev/zero of=filename bs=1 count=0 seek=200T
Из справочной страницы dd:
БЛОКИ И БАЙТЫ могут следовать следующие мультипликативные суффиксы: c = 1, w = 2, b = 512, kB = 1000, K = 1024, MB = 1000 * 1000, M = 1024 * 1024, GB = 1000 * 1000 * 1000, G = 1024 * 1024 * 1024 и т.д. Для T, P, E, Z, Y.
Я не знаю много о Linux, но здесь код C, который я написал, чтобы подделать огромные файлы на DC Share много лет назад.
#include < stdio.h >
#include < stdlib.h >
int main() {
int i;
FILE *fp;
fp=fopen("bigfakefile.txt","w");
for(i=0;i<(1024*1024);i++) {
fseek(fp,(1024*1024),SEEK_CUR);
fprintf(fp,"C");
}
}
сделать файл 1G:
dd if=/dev/zero of=filename bs=1G count=1
Я не думаю, что вы получите гораздо быстрее, чем dd. Узким местом является диск; написание сотен ГБ данных к нему займет много времени, независимо от того, как вы это сделаете.
Но здесь есть возможность, которая может работать для вашего приложения. Если вы не заботитесь о содержимом файла, как насчет создания "виртуального" файла, содержимое которого является динамическим выходом программы? Вместо открытия() файла используйте popen(), чтобы открыть канал во внешнюю программу. Внешняя программа генерирует данные всякий раз, когда это необходимо. Когда труба открыта, она действует так же, как обычный файл, так как программа, открывающая канал, может использовать fseek(), rewind() и т.д. Вам нужно будет использовать pclose() вместо close(), когда вы выполняется с помощью трубы.
Если вашему приложению требуется, чтобы файл был определенного размера, его внешняя программа должна отслеживать, где находится "файл", и отправлять сообщение, когда "конец" был достигнут.
Вы также можете использовать команду "да". Синтаксис довольно прост:
#yes >> myfile
Нажмите "Ctrl + C", чтобы остановить это, иначе он будет потреблять все свободное место.
Чтобы очистить этот файл, выполните следующие действия:
#>myfile
очистит этот файл.
Один подход: если вы можете гарантировать, что несвязанные приложения не будут использовать файлы конфликтующим образом, просто создайте пул файлов разного размера в определенном каталоге, а затем создайте ссылки на них, когда это необходимо.
Например, у вас есть пул файлов:
Затем, если у вас есть приложение, которому нужен файл 1G с именем /home/oracle/logfile, выполните "ln /home/bigfiles/1024M-A /home/oracle/logfile
".
Если это в отдельной файловой системе, вам придется использовать символическую ссылку.
Файлы A/B/etc могут использоваться, чтобы гарантировать отсутствие противоречивого использования между несвязанными приложениями.
Операция связи работает так же быстро, как вы можете.
GPL mkfile - это просто оболочка (ba) sh script вокруг dd; BSD mkfile просто memsets буфер с ненулевым и записывает его повторно. Я бы не ожидал, что первый из них выйдет из-под контроля. Последний может немного уменьшить dd if =/dev/zero, поскольку он опускает чтение, но все, что делает значительно лучше, вероятно, просто создает разреженный файл.
Отсутствует системный вызов, который фактически выделяет пространство для файла без записи данных (и Linux и BSD этого не хватает, возможно, Solaris), вы можете получить небольшое улучшение производительности, используя ftrunc (2)/truncate (1) to расширьте файл до требуемого размера, mmap файл в память, затем напишите ненулевые данные в первые байты каждого блока диска (используйте fgetconf, чтобы найти размер блока диска).
Это самое быстрое, что я мог сделать (это не быстро) со следующими ограничениями:
Это суть этого... `
// include stdlib.h, stdio.h, and stdint.h
int32_t buf[256]; // Block size.
for (int i = 0; i < 256; ++i)
{
buf[i] = rand(); // random to be non-compressible.
}
FILE* file = fopen("/file/on/your/system", "wb");
int blocksToWrite = 1024 * 1024; // 1 GB
for (int i = 0; i < blocksToWrite; ++i)
{
fwrite(buf, sizeof(int32_t), 256, file);
}
`
В нашем случае это для встроенной Linux-системы, и это работает достаточно хорошо, но предпочтет что-то быстрее.
FYI команда "dd if =/dev/urandom of = outputfile bs = 1024 count = XX" была настолько медленной, чтобы быть непригодной.