6

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

Это беспокоило меня (мягко) в течение многих лет, и я хотел бы знать, почему!

Он воспроизводится в (по крайней мере) Windows 7, например, путем загрузки большого файла.

1 ответ1

8

Есть блог MSDN, описывающий, почему Windows ведет себя так, как вы это описываете.

Сначала отметим, что вы видите только NTFS.

Чтобы проверить, что вы сказали, я написал небольшую программу, которая записывает 40 КБ в файл каждые 5 секунд. Файл остается открытым между каждой записью. Вторая программа использует FindFirstFileEx чтобы получить текущий размер файла. В качестве третьего я использую dir в cmd.exe. С этой настройкой я могу точно видеть, что вы описываете.

Причиной этой проблемы является проектное решение, принятое в NTFS. В NTFS (как и в файловой системе Unix) один и тот же файл может находиться в двух каталогах - это называется жесткой ссылкой. Это означает, что у вас есть две директории, каждая из которых имеет запись для файла, и у вас есть сам файл с его свойствами. Размер файла - это свойство, которое принадлежит файлу, поэтому оно хранится там. Но если кто-то захочет получить список файлов в каталоге со свойствами, такими как размер файла, производительность будет очень низкой, если вы будете не только читать сам каталог, но и читать информацию из каждого файла. Данные для одного каталога, вероятно, будут храниться последовательно, но данные для разных файлов, вероятно, будут разбросаны по всему диску. Поэтому NTFS хранит копию размера файла в записи / записи каталога.

Вы, возможно, догадались, это также имеет удар по производительности. Подумайте о 10 жестких ссылках на один файл. Хотите, чтобы NTFS обновляла 10 записей каталога каждый раз, когда вы записываете в файл? Нет. Итак, второе решение о дизайне было принято после Vista: данные в записи каталога обновляются только при закрытии файла.

Вы можете легко это проверить: запустить программу, которая пишет в файл и сохраняет его открытым. Запустите dir и вы не увидите обновленный размер. Или напишите файл с помощью Блокнота (который закрывает файл в конце), и сразу же новый размер файла отобразится в dir или проводнике.

Почему F5 помогает обновить размер файла? Explorer вызывает GetNamedSecurityInfo, который внутренне открывает файл и закрывает его (вы можете проверить это в SysInternals Process Monitor). Если я вызываю GetNamedSecurityInfo в моей собственной программе, а затем вызываю FindFirstFileEx я сразу вижу новый размер файла. Таким образом, наблюдаемое поведение в точности соответствует теории.

Но почему вы не видите новый размер файла сразу в проводнике? Кажется, что Explorer сначала вызывает FindFirstFileEx а затем GetNamedSecurityInfo . Таким образом, Explorer получает старый размер и затем запускает обновление записи каталога. Если вы запустите dir в cmd.exe, вы увидите, что запись в каталоге теперь имеет новый размер файла. Это только, что Explorer еще не знает это. Проводнику требуется второй F5, чтобы получить последний размер, а затем снова вызвать обновление.

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

Кстати, спасибо за этот очень интересный вопрос! Мне нравится изучать такие NTFS interna.

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