Выделить файл без обнуления и создания разреженного файла в Linux
Моя цель - мгновенно выделить много места для файла, не создавая разреженный файл. Чтение из файла должно выводить мусор, оставленный в свободном пространстве, а не 0.
И то и другое truncate
а также fallocate
сделать разреженные файлы.
Это возможно?
0 ответов
Можем ли мы избежать нулей?
Нет, это невозможно.
Ядро, по очевидным причинам безопасности, очищает сектора, которые освобождаются при удалении, усечении и т. Д. Поэтому, когда вы выделяете новый файл, он автоматически обнуляется. Эта очистка может быть виртуальной (в отличие от физической записи нулей на диск, особенно потому, что она не работает на SSD- см. shred(1)
подробнее).
Единственный способ, если вы хотите действительно чрезвычайно быстрое выделение, - это создать свой собственный раздел и управлять им самостоятельно. Непростой подвиг, если вы в настоящее время полагаетесь на многие функции ext4 или другой подобной файловой системы.
Поскольку для секторов уже должны быть установлены нули, не должно быть никакого влияния на скорость при размещении нового (большого) файла на диске.
Редкие файлы
По опыту, когда вы записываете нули в файл, он физически записывает нули на диск. Он вообще не создает разреженный файл.
В программном обеспечении для создания разреженного файла необходимо использовать truncate()
/ftruncate()
функции для увеличения файлов и lseek()
после конца файла до следующего write()
. Однако если вы сделаетеwrite()
из всех нулей ОС не пытается преобразовать их в разреженном файле.
Другими словами, вы можете написать что-то вроде этого на C++, и вы не получите разреженный файл:
int fd = open(filename, O_CREAT | O_WRONLY, 0600);
std::vector<uint8_t> buffer(size);
write(fd, buffer.data(), buffer.size());
close(fd);
В этом примере кода предполагается относительно небольшой size
параметр. В противном случае использование цикла будет намного более эффективным и с меньшей вероятностью взорвет вашу память.
В вашей консоли это означает использование инструмента, который будет записывать каждый байт в целевой файл. Это будет медленным для очень больших файлов (например, запись 1 ТБ... ну вы знаете...) Вот тот, который работает таким образом:
head -c${SIZE} /dev/zero >"${OUTPUT}"
Обратите внимание, что некоторые инструменты специально поддерживают разреженные файлы. Например:
cp
можно использовать для копирования разреженных файлов.dd
выполнит работу по поиску нулей во входном файле и правильноtruncate()
для увеличения вывода без записи нулей.- И т.п.
Конечно, есть очень веские причины для размещения физического файла на диске, даже если эта операция выполняется медленно:
- Вы создаете файл базы данных; в этом случае было бы действительно опасно использовать разреженные файлы (т.е. запись может завершиться неудачно в неподходящее время), а выделение нового индексного дескриптора происходит медленно, поэтому пропускная способность вашей базы данных может быть затронута (хотя это происходит только при записи и увеличении файла базы данных аналогично выделению inode вашему файлу при необходимости).
- Вы создаете виртуальный диск; Я тестировал их с разреженным файлом, и это слишком ужасно; по крайней мере, на моих старых компьютерах с жестким диском он работал слишком медленно при запуске VPS
- Вы создаете файл подкачки; действительно не лучшая идея использовать разреженный файл для свопа (это как нарочно искать проблемы! между медленным выделением новых блоков, тем фактом, что файл, вероятно, будет фрагментирован, возможностью заполнен в то время, когда вам нужно это пространство подкачки...)