1

Иногда я сталкиваюсь с программами, которые записывают файлы длиной 0 байт во время записи, в соответствии с файловой системой, но запись сокращает свободное место на диске, о котором сообщается. Примеры программ: wget загружающий большой файл, или ffmpeg конвертирующий видео.

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

Обычно, если я прерываю операцию, файл неожиданно получает сообщение о «пропущенных» байтах и внезапно увеличивается до «правильного» размера.

Кроме того, если я загляну в файл с помощью Total Commander's Lister, я увижу, что в нем действительно есть содержимое.

Я задавался вопросом, где эти байты? Нет файла, похожего на «.bak», рядом с 0-байтовым файлом. Мой каталог tmp находится на другом диске. Согласно памяти диспетчера задач Memory (private working set) использование памяти программой не увеличивается. А также Lister может отображать контент!

Мой метод проверки размеров файловой системы - с помощью отображаемой информации Total Commander. Я регулярно обновляю каталог, который также обновляет счетчик свободного пространства. Я также протестировал с dir Гав тот же результат. Я на NTFS.

Почему указанный размер не обновляется? Где хранятся данные, которые находятся внутри них?

1 ответ1

5

Это действительно по замыслу. Это давнее поведение операционных систем Microsoft/IBM, которое также можно найти в 32-битной OS/2, 16-битной OS/2, PC-DOS, MS-DOS, а также DR-DOS (также известной как Novell DOS или OpenDOS).

Поведение состоит в том, что запись каталога в файле только обновляется, показывая правильную метку времени последнего изменения, размер и информацию о выделении в списке каталога, когда запись таблицы системных файлов для файла закрыта. Запись SFT закрывается, когда закрыты все открытые дескрипторы во всех процессах, которые ссылаются на нее. Программы, которые находятся в процессе загрузки "сотен MiB", еще не закрыли свои дескрипторы открытых файлов. Поэтому их SFT-записи не закрыты. Таким образом, записи каталога не обновляются.

Если один или несколько дополнительных дескрипторов файла были созданы с помощью DosDupHandle , внутренние буферы для файла не записываются на диск, и его запись в каталоге не обновляется , пока не будет вызван DosClose для всех дескрипторов.
- «Закрытие файлов». OS/2 Warp: Руководство и справочник по программированию управляющей программы . Корпорация IBM.

На однозадачных MS/PC/DR-DOS это несколько трудно наблюдать, хотя это можно наблюдать под DesqView, Windows 3.x в 386 Enhanced Mode, TASKMAX и так далее. На многозадачной ОС /2 это можно было регулярно и легко наблюдать.

Одной из менее приятных особенностей этого поведения было (на томах FAT), что грязное завершение работы до закрытия дескриптора файла привело бы к тому, что CHKDSK увидит файл нулевого размера и обрежет все загруженное до сих пор.

Это было поведение, совершенно отличное от UNIX, где можно было наблюдать рост файла по мере его роста с помощью ls -l потому что команда ls смотрела на i-узел (в оперативной памяти и в актуальном состоянии) для метаданных файла, а не на запись каталога (которая в собственных файловых системах UNIX не имеет информации о размере и дате). DOS, OS/2 и Windows NT также увеличивают размер файла. Блоки данных выделяются для файла, запись SFT отслеживает размер файла, структуры, такие как f-узел (в томах HPFS), обновляются, и, как вы заметили, свободное пространство тома уменьшается. Просто невозможно увидеть, с помощью dir или чего-либо еще, что сообщает о содержимом записи каталога, растущий файл.

Ситуация с Windows NT и NTFS очень похожа на ситуацию с OS/2 и DOS. (Номенклатура изменилась, что немного смущает новичка. Если в DOS и OS/2 имеются записи в таблице системных файлов, на которые ссылаются дескрипторы файлов в отдельных процессах, в Windows NT есть файловые объекты, на которые ссылаются дескрипторы в отдельных процессах.) По иронии судьбы, это больше похоже на поведение старых операционных систем IBM/Microsoft, начиная с Windows NT 6.0, где поведение было изменено. "Новое" поведение NTFS заключается в том, что записи каталога для файла, хранящиеся в каждом из каталогов, которые имеют ссылку на файл и используются при перечислении каталога из Win32 (с FindFirstFile/FindNextFile), обновляются только тогда, когда файл объект для файла закрыт, в то время как метаданные, прикрепленные к самому файлу, не видимые из списка каталогов (и доступные только через вызовы, такие как GetFileInformationByHandle), обновляются как файл.

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

Запись каталога в файле обновляется всякий раз, когда запись таблицы системных файлов для него закрывается, а запись SFT закрывается, когда закрывается последний дескриптор открытого файла в любом процессе, который ссылается на него. Это не должен быть дескриптор, открытый или используемый процессом записи в файл. Можно использовать все, что открывает файл (создает отдельную запись SFT) и закрывает его снова. Это может быть что-то простое, например, команда type запущенная в другой консоли / сеансе:

type file > nul

По иронии судьбы, Total Commander's Lister сделал бы именно это, каждый раз, когда вы использовали его для просмотра содержимого файла во время его записи. Если бы вы заметили это, вы бы здесь спросили, почему Lister Total Commander волшебным образом "исправили" ваш каталог. И ответом было бы то, что в Total Commander нет ничего особенного. Все, что открывалось и закрывалось отдельно, имело бы тот же эффект.

Для полноты заметим, что имелись системные вызовы, которые загружающая программа могла использовать для обновления записи каталога по мере продвижения. OS/2 имеет DosBufReset например. Тем не менее, эти системные вызовы также очищают кэш диска, что не обязательно то, что нужно. Открытие файла во второй раз, а затем закрытие этого дескриптора файла не очищает кэш диска.

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