3

У меня есть несколько копий файла. Файлы занимают 2390170 КБ каждый, в соответствии с ls -lk и du --apparent-size -k .

Проблема в том, что du -k сообщает разные размеры для каждой копии: 2389824, 2392512, 2392512 и 2390336.

Я ожидал, что использование диска должно составлять 2390172 КБ (размер минимального числа блоков (597543), куда помещается файл.

Итак, почему у каждого файла разное использование диска?

Я также видел, что одна из копий использует 2389824 КБ, но размер файла на 346 КБ больше: 2390170. Как это имеет смысл?

PD: Все файлы находятся в одной файловой системе ext3. Размер блока файловой системы составляет 4096. Все файлы имеют одинаковый хэш.

Обновление: из комментариев:

although the apparent size is usually smaller, it may be larger due to holes in ('sparse') files, internal fragmentation, indirect blocks, and the like

редкие файлы могут быть причиной, потому что использование диска ниже. Но я не вижу, как внутренняя фрагментация или косвенные блоки могут уменьшить использование диска по сравнению с исходным файлом. Поскольку файл один и тот же, использование диска из-за внутренней фрагментации и косвенных блоков должно быть постоянным.

Я заметил, что cp --sparse=always может сделать разреженный файл из не разреженного. cp --sparse=always приводит к файлу, который использует 2390336KiB cp --sparse=never приводит к файлу, который использует 2392512KiB

Поэтому я предполагаю, что использование 2389824KiB для одной из копий вызвано другой реализацией разреженного алгоритма ...

Исходный файл был скопирован с компьютера Windows через sftp или samba, и я думаю, что файл 2389824KiB является его копией, но я не помню, как я это сделал (я думаю, что с cp, но я не конечно).

2 ответа2

3

От man du:

--apparent размера
печатать видимые размеры, а не использование диска; хотя видимый размер обычно меньше, он может быть больше из-за дыр в («разреженных») файлах, внутренней фрагментации, косвенных блоков и т. п.

Из info du:

«--Apparent размера»
Печать видимых размеров, а не использование диска. Кажущийся размер файла - это число байтов, сообщаемых wc -c в обычных файлах, или, в более общем случае, ls -l --block-size=1 или stat --format=%s . Например, файл, содержащий слово «zoo» без перевода строки, конечно, будет иметь видимый размер 3. Такой маленький файл может занимать от 0 до 16 КБ или более дискового пространства, в зависимости от типа и конфигурации файловой системы, в которой находится файл. Тем не менее, разреженный файл, созданный с помощью этой команды:

      dd bs=1 seek=2GiB if=/dev/null of=big

имеет очевидный размер 2 ГиБ, но в большинстве современных систем фактически не использует дискового пространства.

[акцент мой]

1

Здесь происходит две вещи - файлы, которые больше, чем вы ожидаете, происходят из-за метаданных, которые хранит файловая система, и которые учитываются по размеру файла. Файлы, которые меньше, чем вы ожидаете, происходят из-за функции UNIX, называемой "разреженные файлы".

Большие файлы

Для ext2/ext3 использование файла на диске включает пространство, используемое структурами файловой системы, которые отслеживают, где находятся блоки данных на диске. Взгляните на структуру inode Ext2 - inode - это структура данных, которая отслеживает разрешения, размер и т.д. Файла, а также местоположение его блоков данных на диске. Сам индекс не учитывается при использовании (он предварительно выделяется при создании файловой системы), но косвенные блоки есть.

расчет

Итак, ваш файл размером 2390172 КБ занимает 597543 блоков данных, как вы сказали. Местоположения 12 из этих блоков хранятся в самом иноде, поэтому они бесплатны. 13-е местоположение, хранящееся в inode, предназначено для косвенного блока - вновь выделенного блока, который хранит местоположения 1024 блоков данных. Таким образом, это добавляет 1 блок к вашему размеру файла и оставляет нам 596507 блоков.

14-й указатель местоположения в inode предназначен для дважды непрямого блока - выделенного блока, который содержит места 1024 косвенных блоков. 596507/1024 ~ = 582,52, поэтому нам понадобится 583 косвенных блока для хранения остальных блоков данных плюс один дважды косвенный блок.

Так:

    1 (indirect from inode)
+   1 (doubly-indirect from inode)
+ 583 (indirect from doubly-indirect)
-----
= 585
= 598128 - 597543

И это составляет 2392512 (= 598128 * 4).

Меньшие файлы

Я подозреваю, что файлы меньшего размера (2389824 КБ) являются разреженными файлами, что означает, что некоторые из блоков никогда не записывались и поэтому не были распределены - нераспределенные блоки определяются как заполненные нулями. См. Ответ Денниса Уильямсона для справок. Разреженные файлы могут возникать, если программа записи перемещает указатель файла и записывает в разные позиции в файле, а не записывает файл с начала до конца. Для крайнего примера разреженного файла попробуйте следующее:

du if=/dev/zero of=my_sparse_file bs=1000 count=1 seek=1000000

Если ls результирующего файла, видимый размер будет 1000001000. Однако поскольку записано только 1000 байтов, используется только один блок данных, поэтому выделяется только один блок данных. du сообщит об использованных 12 КБ - один блок 4 КБ для данных, один для блока с двойным косвенным отображением и один для одного косвенного блока, на который указывает блок с двойным косвенным значением с помощью своего 976-го указателя. Ни один из остальных блоков файла не был выделен, будь то данные или метаданные.

Как только заканчивается дважды косвенный блок, файловая система начинает использовать трижды косвенный блок. Ваш файл достигнет максимально возможного размера файловой системы ext3, прежде чем заполнить его.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .