Глубины ввода-вывода Windows (часть 5) — внутреннее устройство NTFS: файловая система через MFT

· · Windows, NTFS, I/O, Файловая система, MFT, Ядро, .NET, Расследование ошибок

За четыре предыдущие части мы проследили, как течёт запрос I/O (части 1–3) и как его принимает диспетчер кэша (часть 4). В конце запрос приходит в файловую систему. На этот раз очередь её главного представителя — NTFS.

Точка зрения меняется. До сих пор речь была динамическая — поток запроса. Теперь статическая история о том, как данные лежат на диске. Суть невидимого «Zone.Identifier» у скачанного файла. Почему копирование десяти тысяч мелких файлов гораздо медленнее одного файла того же суммарного размера. Насколько правда «NTFS журналируемая — значит спокойно» — всё объясняется из этой структуры.

Это часть 5 серии «Глубины ввода-вывода Windows».

Предпосылка этой части: базовые IRP и стек устройств части 1 делают чтение легче. Но чтобы читать и отдельно, термины предыдущих частей сначала определим.

Термин Одной строкой Подробнее
IRP (I/O Request Packet) «Накладная запроса I/O», в которую внутри ядра превращается вызов API вроде ReadFile. Драйвер принимает эту накладную и обрабатывает Часть 1
Диспетчер I/O и стек устройств Часть ядра, которая делает IRP и по очереди передаёт его драйверам, сложенным до целевого устройства, и сама эта стопка Часть 1
Диспетчер кэша Часть, которая держит содержимое файла в памяти и позже пакетом пишет на диск то, что пришло в WriteFile. Источник «сразу после записи на диск ещё не обязательно попало» Часть 4

Таблица 1: термины предыдущих частей, которые эта часть предполагает

Ещё одно: два этапа из части 1 — cleanup (когда закрылся последний дескриптор) и close (когда исчезли все ссылки внутри ядра) — понадобятся в объяснении удаления файла в главе 4.

1. Сначала вывод

  • Центр NTFS — MFT (главная файловая таблица). Все файлы ведутся как записи в MFT; вся информация о файле — «внутри записи MFT» или «в области вне MFT, на которую запись указывает» (глава 2).1
  • Сущность файла — «набор атрибутов». Маленький файл целиком, вместе с данными, помещается в запись MFT (резидентный), большой держит только ссылку на прогон кластеров (нерезидентный). Медленность массовой обработки мелких файлов объясняется отсюда (глава 2).1
  • Данных может быть несколько (несколько потоков данных). Обычные данные — «безымянный поток»; дополнительный поток задают как file.txt:имя. Суть Zone.Identifier (Mark of the Web) (глава 3).2
  • Имя тоже атрибут. Несколько имён у одной записи — жёсткая ссылка. Сокращённое имя 8.3 тоже живёт рядом как «ещё одно имя» (глава 4).34
  • Точка повторного разбора — официальный механизм «открыл — и в другом месте». Символические ссылки, соединения и Files On-Demand OneDrive — все приложения этих данных с тегом (глава 5).56
  • Журналов два. $LogFile — для восстановления согласованности метаданных (опережающий журнал, чтобы не сломаться), журнал USN — для записи истории изменений (реестр «что изменилось»). Роли совершенно разные (глава 6).78
  • «Размер» и «размер на диске» — разные вещи. Разрыв дают разреженные файлы и сжатие. Фон «сжатый файл не становится асинхронным» из части 2 тоже здесь (глава 7).910

Карта знаний этой статьи

Центр NTFS — MFT (главная файловая таблица): все файлы ведутся как записи в MFT. Маленькие данные резидентны внутри записи, большие — нерезидентны и держат только ссылку на прогон кластеров; в этом суть медленности массовой обработки мелких файлов и фрагментации. Несколько потоков данных, жёсткие ссылки и сокращённые имена 8.3 — приложения того же механизма «набор атрибутов»; точка повторного разбора — официальный крючок на «открыть», который держит от символической ссылки до Files On-Demand OneDrive. $LogFile защищает согласованность структуры; долговечность содержимого данных нужно отдельно строить инструментами управления кэшем части 4.

Карта знаний внутреннего устройства NTFS и MFTРисунок, показывающий связи NTFS, MFT, записи файла, резидентных и нерезидентных атрибутов, прогонов данных, фрагментации, нескольких потоков данных, Zone.Identifier, жёстких ссылок, сокращённых имён 8.3, точек повторного разбора (символическая ссылка, соединение, Files On-Demand OneDrive), $LogFile и журнала USN, разреженных файлов и сжатия NTFSиспользуетиспользуеттребуетснижаетиспользуетиспользуетнесовместимо сиспользуетможет вызватьпроверяетсяиспользуетхранится впроверяетсяпроверяетсяможет вызватьиспользуеттребуетиспользуетнастраиваетсяиспользуетпроверяетсяреализуетреализуетреализуетиспользуетснижаетиспользуетиспользуетпроверяетсяиспользуетможет вызватьиспользуетможет вызватьнесовместимо спроверяетсяNTFSMFT (главная файловая таблица)запись файла MFTзона MFTфрагментация (NTFS)резидентный атрибут (resident)нерезидентный атрибут (non-resident)прогон данныхfsutilальтернативный поток данных (ADS)Zone.Identifier (Mark of the Web)streams (Sysinternals)расхождение логического размера и использования дискажёсткая ссылкасокращённое имя 8.3точка повторного разборасимволическая ссылкасоединение (точка монтирования)Files On-Demand OneDrive$LogFile (журнал транзакций NTFS)повреждение томадиспетчер кэшажурнал USN (журнал изменений)разреженный файлсжатие NTFSасинхронный ввод-выводProcess Monitor (procmon.exe)

На схеме сплошная линия обозначает отношение, которое выполняется всегда, а пунктирная — условное отношение (условия указаны в пояснении к каждому отношению на странице сведений). Полный список отношений (всего 35, с доказательствами и степенью уверенности) и определения основных понятий собраны на странице сведений карты знаний (на японском). Данные: JSON-LD / Turtle

2. Всё — записи MFT

2.1. Реестр тома

При форматировании тома NTFS создаются MFT (master file table) и ряд файлов метаданных, имена которых начинаются с $. В MFT есть хотя бы одна запись на каждый файл тома, и запись самой MFT тоже входит.1

Том NTFSзапись указывает на положение$MFT ── главная файловая таблицареестр записей всех файлов (сама тоже в нём)Область данных пользователя(место нерезидентных данных)$LogFile ── журнал транзакцийопераций над метаданными (глава 6)$Bitmap ── использование кластеров$Boot / $Secure / $UpCase и др.прочие файлы метаданных

Рис. 1: Структура тома NTFS. «Управленческая информация самой файловой системы тоже живёт как файлы» — устройство NTFS.

Сведения о файле — размер, метки времени, права доступа и вплоть до содержимого данныххранятся внутри записи MFT или в области вне MFT, положение которой описывает запись.1 При удалении файла запись помечается «свободной» и идёт в повторное использование, но сама MFT не сжимается. Чтобы держать MFT непрерывной, резервируется область зоны MFT; когда том заполняется, начинается фрагментация MFT — даже этот срок жизни описан в официальной документации.1

2.2. Файл = набор атрибутов, резидентный и нерезидентный

Содержимое записи файла — список атрибутов. Стандартные сведения (метки времени и т. п.), имя файла, безопасность и данные. Здесь важная развилка.

Запись файла MFT (реестр на один файл)примерно до сотен байтбольшеАтрибут стандартных сведенийметки времени, флаги атрибутовАтрибут имени файла(может быть несколько ── глава 4)Атрибут данныхДанные маленькие?Резидентный (resident)само содержимое помещается в записьчтение заканчивается одним доступом к MFTНерезидентный (non-resident)в записи только «ссылка на прогон кластеров»сами данные — в области пользователя

Рис. 2: Запись файла — набор атрибутов. Если данные малы, они «резидентны» внутри записи.

Как одно и то же содержимое записи выглядит у резидентного и нерезидентного — рядом понятнее.

Нерезидентный (non-resident) ── большой файлуказывает на положениеуказывает на положениеЗапись файла MFT (фиксированная длина)стандартные сведения / имя / безопасность─────────────атрибут данных = таблица прогонов данныхряд «откуда сколько кластеров»Область данных пользователяпрогон 1: непрерывные кластерыОбласть данных пользователяпрогон 2: непрерывные кластеры в другом местеРезидентный (resident) ── маленький файлЗапись файла MFT (фиксированная длина)стандартные сведения / имя / безопасность─────────────атрибут данных = само содержимое«значение настройки = 1» лежит здесь напрямуюОтдельного места на диске нетчтение заканчивается доступом к MFT

Рис. 3: Резидентный против нерезидентного. У нерезидентного в записи только таблица «где сколько настоящих данных» (прогоны данных).

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

Из этой структуры объясняется несколько явлений с площадки.

  • Почему копирование десяти тысяч мелких файлов медленное. На каждый файл — создание записи MFT, регистрация имени, настройка безопасности: операции над метаданными. Не сам перенос данных доминирует, а работа реестра (и каждая из них ещё станет целью проверки фильтров части 6).
  • Суть фрагментации. Нерезидентные данные записываются как «ряд непрерывных участков кластеров (прогонов)». Если непрерывную область не взять, число прогонов растёт, растёт число нужных позиционирований — это фрагментация. Реальный ряд прогонов можно подсмотреть fsutil file layout.
  • «Папка» ничем не особенная. Каталог — «файл с указателем (индексом) от имени файла к номеру записи MFT». На уровне реестра всё сидит на одном механизме.

3. Данные — лишь один из «потоков»

3.1. Один файл, несколько последовательностей байтов

В NTFS один файл может держать несколько потоков данных. То, что обычно читают и пишут ReadFile/WriteFile, — безымянный поток по умолчанию; синтаксисом имя_файла:имя_потока делают альтернативный поток данных (ADS).2

Файл report.docx (одна запись MFT)Поток по умолчанию (безымянный)= содержимое, которое обычно видят:Zone.Identifierсведения об источнике (Mark of the Web):произвольное имясобственные добавки приложения

Рис. 4: Несколько потоков данных. В размере проводника виден только поток по умолчанию.

Самый близкий ADS — Zone.Identifier. У файла, скачанного браузером, в этом потоке записан источник (из интернета и т. п.); это материал решения SmartScreen «Windows защитил ваш компьютер» и защищённого просмотра Office. Лицевая сторона этого механизма — в «Почему Windows показывает сообщение „Windows защитил ваш компьютер“»; изнанка — просто поток NTFS.

3.2. Ловушки, в которые попадает разработчик

  • Не видно. Ни в размере проводника, ни в списке dir. Проверяют dir /r или streams из Sysinternals.11
  • Не увезти. ADS — функция NTFS, при копировании через USB на FAT или через облачное хранилище часто теряется. «Предупреждение о скачивании пропало после копирования» — это оно.
  • Своё приложение тоже может открыть. Достаточно двоеточия в пути: CreateFile("data.txt:meta", ...).2 Удобно, но вместе с этим принимаете свойство «не увезти» из предыдущего пункта — не место для тела бизнес-данных.

4. Имя тоже атрибут — жёсткие ссылки и имена 8.3

4.1. Жёсткая ссылка — несколько имён одной записи

На рис. 2 было «атрибут имени файла может быть несколько». Внутри одного тома несколько путей ссылаются на один файл — это жёсткая ссылка (CreateHardLink / mklink /H).3

Индекс C:\backup\Индекс C:\app\config-link.json → запись #1234config.json → запись #1234Запись MFT #1234тело данных (или ссылка на прогоны)число ссылок: 2

Рис. 5: Жёсткая ссылка. Индекс каталога указывает на одну и ту же запись MFT — оба «настоящие».

Изменение через любое имя — тот же файл, содержимое сразу совпадает.3 И меняется смысл «удаления»: DeleteFile — «снять одно имя», а сущность исчезает, только когда снято последнее имя, закрыты открытые дескрипторы и исчезли все ссылки внутри ядра, включая секции проекции в память. Два этапа из части 1 — cleanup (последний дескриптор) и close (последняя ссылка) — прямо работают и на срок жизни удаления. У отображения атрибутов есть странность: смена атрибута через одну ссылку может оставить видимое отображение других ссылок старым — это официально отмечено.3

4.2. Имя 8.3 — ещё одно скрытое имя

Ради исторической совместимости NTFS может автоматически порождать для длинного имени сокращённое имя формата 8.3 вроде REPORT~1.DOC. Оно тоже живёт в записи как «ещё одно имя». В папке с массой файлов порождение и разбор столкновений сокращённых имён стоит денег, поэтому fsutil 8dot3name умеет выключить порождение и снять уже существующие (если старое приложение записало путь в реестре сокращённым именем, сломается — поэтому перед strip есть проверка, это практичный момент).4

Важно: есть ли сокращённое имя — зависит от среды. Поведение по умолчанию задаёт значение реестра NtfsDisable8dot3NameCreation: 0 (порождать на всех томах), 1 (не порождать ни на одном), 2 (настраивать по томам), 3 (не порождать кроме системного тома).4 При 2 можно переключать по томам, поэтому «в Windows обязательно есть сокращённое вроде PROGRA~1» — неверно. Прежде чем писать код или процедуру, зависящие от сокращённого имени, проверьте текущее состояние: fsutil 8dot3name query C: (без тома — общая настройка по умолчанию).

Ловушки путей и имён (MAX_PATH, зарезервированные имена, конечная точка) подробно — в «MAX_PATH и подводные камни путей/имён файлов в Windows». Разрешение имён части 1 (диспетчер объектов) плюс эта глава (имена внутри файловой системы) дают общую картину «имени» в Windows.

5. Точка повторного разбора — механизм «открыл — и в другом месте»

Файлу или каталогу можно повесить точку повторного разбора. Сущность — атрибут «тег + данные, заданные пользователем». Когда файловая система открывает файл с точкой повторного разбора, обработка перехватывается по тегу: либо драйвер фильтра, который понимает тег, берёт обработку на себя, либо при теге переименования разрешение начинается заново с пути назначения.5

NTFSДиспетчер I/OПриложениеNTFSДиспетчер I/OПриложениеУ цели найдена точка повторного разборавозвращаются тег и данныеФильтр, понимающий тег,берёт обработку (часть 6)alt[Символическая ссылка / соединение(переименование)][Тег, которым управляет фильтр (облачные файлы и т.п.)]CreateFile("C:\data\link.txt")IRP_MJ_CREATE (мир части 1)«Настоящее место — вот»Разрешение заново по пути назначения

Рис. 6: Разрешение точки повторного разбора. Официальный крючок на операцию «открыть».

На одном этом механизме стоят привычные функции.

  • Символическая ссылка (mklink) — указатель, держащий путь назначения. Может указывать на другой том и UNC.6
  • Соединение / точка монтирования — старый механизм связать каталог с местом на другом локальном томе.3
  • Files On-Demand OneDrive — файл без содержимого под рукой представляют точкой повторного разбора, в момент открытия фильтр скачивает и подставляет содержимое. Суть «в проводнике видно, а при открытии идёт сеть» (сам механизм фильтра — в части 6).

Практическое замечание одно. «То, что в конце пути, не обязательно именно это локальное место». Инструмент, который рекурсивно обходит дерево, зацикливается на соединении; суммирование размеров двоится; резервное копирование массово материализует облако — код, который не знает о точках повторного разбора, наступает сюда. Вход в защиту — проверка атрибута FILE_ATTRIBUTE_REPARSE_POINT семейства FindFirstFile.5

6. Два журнала — $LogFile и USN

«NTFS — журналируемая файловая система» говорят часто, но у NTFS два журнала с разной ролью. Смешаете — неверно прочитаете гарантию.

Журнал USN ── история изменений (чтобы знать, что изменилось)При каждом изменении файла / каталогазаписывают содержимое изменения и имяРезервное копирование, поисковый индекс, синхронизациявидят «что изменилось с прошлого раза» без полного обхода$LogFile ── опережающий журнал (чтобы не сломаться)Операции над метаданными (обновление записи, смена имени и т. п.)записывают в журнал до выполненияПри следующем запуске после сбоя системыжурнал воспроизводят и восстанавливают согласованность структуры

Рис. 7: Два журнала. $LogFile — чтобы «не сломаться», USN — чтобы «знать об изменениях».

Разница таблицей.

Аспект $LogFile (журнал транзакций) Журнал USN (журнал изменений)
Цель После сбоя вернуть структуру файловой системы в согласованное состояние7 Позже узнать «что изменилось с прошлого раза»8
Что записывают Опережающий журнал операций над метаданными (обновление записи, смена имени и т. п.). Содержимое файла не цель При каждом изменении — содержимое изменения и имя целевого файла/каталога8
Кто пользуется Сама NTFS. Автовосстановление при следующем монтировании Приложения: резервное копирование, поисковый индекс, синхронизация
Как далеко назад Только диапазон, нужный для восстановления. Фиксированный размер крутится, для истории прошлого не годится При превышении целевого максимума (MaximumSize) на контрольной точке старые записи отрезаются с начала. Насколько далеко — от настройки размера и объёма обновлений тома12
Как смотреть Официального чтения содержимого нет (размер смотрят chkdsk /L) Состояние — fsutil usn queryjournal, содержимое — fsutil usn readjournal. Из программы — FSCTL_QUERY_USN_JOURNAL / FSCTL_READ_USN_JOURNAL12
Можно ли остановить Нельзя (часть NTFS) Администратор может удалить и выключить. Но это заставляет пользующиеся службы делать полный обход — влияние большое12

Таблица 2: Два журнала рядом

  • $LogFile (журнал транзакций)опережающий журнал операций над метаданными. Даже при сбое системы NTFS при следующем запуске автоматически восстанавливает согласованность файловой системы из этого журнала и сведений контрольной точки.7 Здесь защищена структура. Как в части 4, грязное содержимое данных в кэше при отключении питания может пропасть — правильное чтение: «том не сломается. Но последняя запись может исчезнуть».
  • Журнал USN (журнал изменений) — реестр, который при каждом изменении файла или каталога на томе записывает содержимое изменения и имя цели.8 Механизм, которым резервное копирование и индексатор берут «только то, что изменилось с прошлого раза» без полного обхода; ещё — чтобы избежать перестройки индекса после сбоя.8 На практике полезно помнить: fsutil usn readjournal можно взять сверкой, которая дополняет пропуски FileSystemWatcherПрактическое руководство по FileSystemWatcher»).

7. Разреженные файлы и сжатие — история про два «размера»

В NTFS логическая длина файла и реально выделенная область ведутся отдельно. На экране свойств это «размер» и «размер на диске». Два главных источника разрыва.

Разреженный файл диапазонам из одних нулей реальное место не выделяет — ведёт как «дыры».9 Файл виртуального диска с логическим размером 42 ГБ на диске занимает 500 МБ — обычное дело. Чтение дыры возвращает нули; запись выделяет ровно столько.

Выделение на диске (15 МБ + управленческая информация)Логический файл (размер: 1 ГБ)Прогон: сущность R1Прогон: сущность R2Данные 10 МБДыра (нули) 500 МБДанные 5 МБДыра (нули) остальное

Рис. 8: Разреженный файл. У «дыры» выделения нет, логический размер и размер на диске расходятся.

Сжатие NTFS хранит данные, сжатые единицами сжатия.10 Прозрачно и удобно, но стоимость тоже не прозрачна: при каждом чтении и записи идут развёртка и повторное сжатие, фрагментация легче растёт. И как в главе 5 части 2, доступ к сжатому файлу не становится асинхронным (файловая система превращает его в синхронный). Одно из мест, которое подозревать, когда «сделали асинхронный I/O, а этот файл не ускорился».

Реальный размер по выделению даёт GetCompressedFileSize. В расследовании «сумма размеров файлов» не сходится с «использованием диска» стандарт — по очереди подозревать разреженность, сжатие, ADS (глава 3) и округление по кластерам.

8. Проверить своими глазами

И на этот раз всё можно наблюдать на своём Windows (часть команд — с правами администратора). Чтобы самим судить, верен ли результат, у каждой команды — куда смотреть и что из этого видно.

:: Смотреть альтернативные потоки данных
dir /r C:\Users\%USERNAME%\Downloads

Куда смотреть: под обычной строкой файла с отступом идут строки вида имя_файла:Zone.Identifier:$DATA с длиной. Если такая строка есть, у файла висит Mark of the Web (глава 3). У скачанных браузером — есть, у созданных самим — нет. Запустите в обоих местах и сравните — наличие ADS станет очевидным.

:: Раскладка файла на MFT (прогоны) и атрибуты
fsutil file layout C:\path\to\file.dat

:: Только экстенты (подкоманда из официальной документации)
fsutil file queryextents C:\path\to\file.dat

Куда смотреть: layout по потокам выводит размер, выделенный размер и, если нерезидентный, список экстентов (пары VCN·LCN·число кластеров). Очень маленький файл без строк экстентов — резидентный (п. 2.2); если строк несколько — фрагментирован. Сравнить текстовый файл в несколько байт и файл в сотни мегабайт — самый короткий способ прочувствовать резидентный / нерезидентный.

:: Настройка порождения имён 8.3 и уже существующие сокращённые
fsutil 8dot3name query C:
dir /x

Куда смотреть: query отвечает, включено ли порождение сокращённых имён на этом томе (без тома — общая настройка по умолчанию).4 dir /x рядом с длинным именем показывает столбец сокращённого: пустой столбец значит сокращённого нет. «Сокращённого имени может не быть» из п. 4.2 проверяется на своей среде.

:: Состояние журнала USN
fsutil usn queryjournal C:

Куда смотреть: идентификатор журнала, диапазон действующих USN (First USN / Next USN), целевой максимум (MaximumSize) и единица выделения (AllocationDelta).12 Создайте какой-нибудь файл и выполните снова — Next USN должен продвинуться: это подтверждение «изменение записано». MaximumSize — ориентир «как далеко назад» из главы 6. На томе с выключенным журналом будет ошибка.

:: Проверка точки повторного разбора (назначение и тег)
dir /aL C:\Users\%USERNAME%
fsutil reparsepoint query "C:\Users\%USERNAME%\OneDrive"

Куда смотреть: то, что вышло в dir /aL, — точки повторного разбора (стоит FILE_ATTRIBUTE_REPARSE_POINT). Символические ссылки и соединения показываются с типом вроде <SYMLINKD> <JUNCTION>. fsutil reparsepoint query выводит значение тега повторного разбора и, если это переименование, путь назначения. Цель без точки повторного разбора даёт ошибку — сама ошибка подтверждает «здесь обычная папка».

Если гнать файловые операции в Procmon, герои этой части идут своими именами (запись в $LogFile, пути с именем потока, обработка повторного разбора). Как пользоваться — в «Практическое руководство по Process Monitor (ProcMon)».

9. Итог

  • Центр NTFS — MFT. Все файлы — записи реестра; сведения — «внутри записи» или «во внешней области, на которую запись указывает». Маленькие данные резидентны, большие — ссылка на прогоны; медленность массовой обработки мелких файлов и фрагментация — следствия этой структуры.1
  • Потоков данных может быть несколько. Zone.Identifier (Mark of the Web) — просто ADS, виден через dir /r, за пределы NTFS не уезжает.211
  • Имя — атрибут, их может быть несколько. Жёсткая ссылка — равные имена одной записи, имя 8.3 — ещё одно имя ради совместимости. «Удаление = снять имя»; сущность исчезает, когда пропали последнее имя, дескрипторы и ссылки внутри ядра (отображённые секции и т. п.).34
  • Точка повторного разбора — официальный крючок на «открыть»; символическая ссылка, соединение и Files On-Demand — его приложения. Код, обходящий дерево, должен учитывать FILE_ATTRIBUTE_REPARSE_POINT.56
  • Журналов два. $LogFile — восстановление согласованности структуры (не сломаться), USN — история изменений (что изменилось). «Журналируемая — значит и данные в безопасности» — нет: долговечность данных строят инструментами части 4.78
  • Логический размер и выделение — разные вещи. Разреженность, сжатие, ADS, округление по кластерам — четыре главных причины «размеры не сходятся». В том числе то, что сжатый файл не становится асинхронным I/O, — ящик расследования производительности.910

Продолжение — финал, часть 6 «Фильтры и минифильтры — почему Procmon и антивирус могут перехватывать I/O». Те, кто с части 1 нет-нет да появлялся «посередине» — антивирус, Procmon, OneDrive, шифрование — как встают в I/O. Финал серии: кто живёт в щелях стека устройств.

Похожие статьи

Смежные области консультирования

KomuraSoft LLC занимается проектированием и расследованием Windows-бизнес-приложений, корни которых в устройстве NTFS: странное поведение размера файла и скорости копирования, сбои вокруг ссылок и потоков.

Справочные ссылки

  1. Microsoft Learn, Master File Table. О том, что у каждого файла на томе NTFS в MFT есть хотя бы одна запись и запись самой MFT тоже входит; о том, что все сведения о файле — размер, метки времени, права доступа, содержимое данных — хранятся внутри записи MFT или в области вне MFT, положение которой описывает запись; о том, что при удалении файла запись помечается свободной и идёт в повторное использование, но размер MFT не уменьшается; о резервировании зоны MFT, чтобы держать MFT непрерывной; о фрагментации MFT по мере выделения.  2 3 4 5 6

  2. Microsoft Learn, File Streams. О том, что данные файла NTFS хранятся как один или несколько потоков; о безымянном потоке данных по умолчанию и именованных альтернативных потоках данных; о открытии потока через CreateFile в форме «имя_файла:имя_потока».  2 3 4

  3. Microsoft Learn, fsutil 8dot3name. О том, что NTFS может порождать для длинного имени сокращённое формата 8.3; о том, что fsutil 8dot3name умеет запрашивать и задавать включение/выключение порождения, снимать существующие сокращённые (strip) и сканировать ссылки реестра, которые пострадают при снятии.  2 3 4 5

  4. Microsoft Learn, Reparse points. О том, что точка повторного разбора — набор данных, заданных пользователем, и тега повторного разбора, однозначно идентифицирующего формат этих данных; о том, что при открытии файла с точкой повторного разбора файловая система пытается обработку, соответствующую тегу (обработку фильтром файловой системы, который понимает тег); о применении в ссылках файловой системы NTFS и удалённом хранилище (иерархическая память); о проверке существования атрибутом FILE_ATTRIBUTE_REPARSE_POINT.  2 3 4

  5. Microsoft Learn, NTFS overview. О том, что NTFS пользуется файлом журнала и сведениями контрольной точки и при сбое системы при следующем запуске автоматически восстанавливает согласованность файловой системы, воспроизводя журнал транзакций; о динамическом переназначении плохих секторов и self-healing NTFS, которая в фоне чинит лёгкие повреждения.  2 3 4

  6. Microsoft Learn, Change Journals. О том, что при каждом изменении файла или каталога на томе в журнал изменений USN этого тома записываются содержимое изменения и имя целевого файла/каталога; о ведении журнала на том; о применении для восстановления индекса файловой системы после сбоя и избежания полной переиндексации тома.  2 3 4 5 6

  7. Microsoft Learn, Sparse Files. О том, что в разреженном файле большим диапазонам из нулей физическое место на диске не выделяется, а выделяется только частям с данными; о том, что чтение невыделенного диапазона возвращает нули.  2 3

  8. Microsoft Learn, File Compression and Decompression. О том, что сжатие файлов NTFS прозрачно и данные сжимаются и хранятся единицами сжатия; о получении размера после сжатия (реального выделения) через GetCompressedFileSize; о стоимости развёртки и повторного сжатия при чтении и записи сжатого файла.  2 3

  9. Microsoft Learn, Streams - Sysinternals. О том, что утилита streams из Sysinternals умеет перечислять и удалять альтернативные потоки данных файлов NTFS.  2

  10. Microsoft Learn, Creating, Modifying, and Deleting a Change Journal и fsutil usn. О том, что MaximumSize журнала изменений — целевое значение и при превышении суммы MaximumSize и AllocationDelta NTFS обрезает его на контрольной точке; о том, что AllocationDelta — единица добавления в конец журнала и удаления с начала; о просмотре состояния и ёмкости через fsutil usn queryjournal и содержимого через readjournal; о FSCTL_CREATE_USN_JOURNAL / FSCTL_QUERY_USN_JOURNAL / FSCTL_READ_USN_JOURNAL / FSCTL_DELETE_USN_JOURNAL из программы; о том, что удаление и выключение активного журнала сопровождаются обходом всей MFT и заставляют службы, которые журналом пользуются, заново сканировать том.  2 3 4

Недавние статьи с теми же тегами помогут подробнее изучить близкие темы.

Теневое копирование тома (VSS): устройство и практика — почему резервное копирование может скопировать файл, который ещё используется

Занятый файл обычно нельзя скопировать из-за нарушения совместного доступа — как тогда это делает ПО резервного копирования? Статья разби...

Эти страницы показывают тему статьи в более широком контексте услуг и решений.

Статья напрямую связана со следующими услугами.

Частые вопросы

Вопросы, которые часто возникают при консультациях по теме статьи.

Что такое MFT (главная файловая таблица)?
Это структура данных в сердце тома NTFS — реестр, в котором у каждого файла на томе есть хотя бы одна запись (запись файла), включая запись самой MFT. Всё о файле — размер, метки времени, права доступа и вплоть до содержимого данных — хранится либо внутри записи MFT, либо в области вне MFT, на которую запись указывает. Маленький файл целиком, вместе с данными, помещается в свою запись MFT (резидентный); у большого в записи только ссылка на раскладку данных (прогон кластеров) (нерезидентный). Удаление файла помечает запись свободной для повторного использования, но размер самой MFT не уменьшается.
Что за невидимые данные «Zone.Identifier» у файлов?
Один из нескольких потоков данных NTFS (альтернативный поток данных). В NTFS один файл может держать несколько последовательностей байтов (потоков); то, что обычно читают и пишут, — безымянный поток по умолчанию. Windows записывает, откуда файл (например, скачан из интернета) в дополнительный поток, который задают через двоеточие: «file.txt:Zone.Identifier». Это так называемый «Mark of the Web», на нём SmartScreen и защищённый просмотр Office строят решения. Альтернативные потоки не видны в размере проводника; проверить их можно командой dir /r или инструментом streams из Sysinternals. Важно: при копировании на файловую систему не-NTFS вроде FAT они не сохраняются.
Чем жёсткая ссылка отличается от символической?
Жёсткая ссылка — «ещё одно имя равного статуса, указывающее на ту же сущность файла — ту же запись MFT». Создаётся только внутри одного тома, доступ по любому имени даёт тот же файл, удаление одного имени файл не убирает, пока остаётся другое. Символическая ссылка — «указатель, который направляет на другой путь», реализована как точка повторного разбора. Она держит только строку целевого пути, поэтому может указывать на другой том и даже удалённо, но становится тупиком, если цель исчезла. На практике: жёсткая ссылка — чтобы разделить сущность (меняется смысл удаления), символическая — чтобы перенаправить путь (перенос или перенаправление).
NTFS — журналируемая файловая система, значит данные переживают отключение питания?
Нужно точно понять, что защищено. Журнал транзакций NTFS ($LogFile) защищает согласованность структуры файловой системы (метаданных). Даже при сбое системы NTFS при следующем запуске автоматически восстанавливает согласованность по журналу и не даёт тому «сломаться так, что не читается». Но само содержимое файла, который писали посередине, от этого не восстанавливается. Как в части 4 серии, грязные данные в кэше при отключении питания пропадают. Правильное понимание — «том не сломается, но содержимое последней записи всё ещё может исчезнуть»; если нужна долговечность самих данных, её нужно строить самим: FlushFileBuffers, WRITE_THROUGH или запись приложения вроде «во временный файл, потом переименовать».
Почему «размер» файла отличается от «размера на диске»?
Потому что NTFS ведёт логическую длину файла и реально выделенное место на диске отдельно. Даже у обычного файла есть разница из-за округления выделения до целых кластеров (по умолчанию 4 КБ), но большой разрыв — у разреженных и сжатых файлов. Разреженный файл диапазонам из одних нулей реальное хранилище не выделяет — ведёт их как «дыры» — поэтому файл с логическим размером в несколько гигабайт может занимать на диске лишь несколько мегабайт. У сжатого выделяется только размер после сжатия. Если наоборот «размер на диске» кажется больше, часто виноваты округление по кластерам или альтернативный поток данных.

Об авторе

Страница с профилем автора статьи.

Го Комура

Представитель KomuraSoft LLC

Специализируется на разработке программного обеспечения для Windows, техническом консалтинге и расследовании сбоев, особенно в проектах с унаследованными системами и трудно воспроизводимыми ошибками.

Публичные ссылки

Вернуться в блог