Предыдущий пример сжатия разреженного файла довольно надуманный. Он описывает «сжатие» в том случае, когда целые области файла заполнены нулями, но на остальные файловые данные сжатие не оказывает никакого влияния. B большинстве файлов данные не являются разреженными, тем не менее их можно компрессировать по какому-нибудь алгоритму сжатия.
B NTFS пользователи могут сжимать отдельные файлы или все файлы в каталоге. (Новые файлы, создаваемые в сжатом каталоге, сжимаются автоматически. Файлы, существовавшие в каталоге до его сжатия, должны быть сжаты индивидуально.) Сжимая файл, NTFS разбивает его необработанные данные на единицы сжатия (compression units) длиной по 16 кластеров. Некоторые последовательности данных в файле могут сжиматься недостаточно сильно или вообще не сжиматься, поэтому для каждой единицы сжатия NTFS определяет, будет ли при ее сжатии получен выигрыш хотя бы в один кластер. Если сжатие не позволяет освободить даже один кластер, NTFS выделяет 16-кластерную группу и записывает единицу сжатия на диск, не компрессируя ее данные. Если же данные можно сжать до 15 или менее кластеров, NTFS выделяет на диске ровно столько кластеров, сколько нужно для хранения сжатых данных, после чего записывает данные на диск. Рис. 12–39 иллюстрирует сжатие файла, состоящего из четырех групп. Незакрашенные области отражают дисковое пространство, которое файл будет занимать после сжатия. Первая, вторая и четвертая группы сжимаются, а третья — нет. Ho даже с одной несжатой группой достигается экономия 26 кластеров диска, т. е. длина файла уменьшается на 41 %.
ПРИМЕЧАНИЕ Хотя на схемах, приведенных в этой главе, показаны непрерывные LCN, единицы сжатия не обязательно располагаются в физически смежных кластерах. Группы, занимающие несмежные кластеры, заставляют NTFS создавать несколько более сложные записи MFT, чем показанные на рис. 12–39.
При записи данных в сжатый файл NTFS гарантирует, что каждая группа будет начинаться на виртуальной 16-кластерной границе. Таким образом, начальный VCN каждой группы кратен 16, и длина группы не превышает 16 кластеров. При работе со сжатым файлом NTFS единовременно считывает и записывает минимум одну единицу сжатия. Ho при записи сжатых данных NTFS пытается помещать единицы сжатия в физически смежные области, так чтобы их можно было считывать в ходе одной операции ввода-вывода. Размер единицы сжатия в 16 кластеров выбран для уменьшения внутренней фрагментации: чем больше размер единицы сжатия, тем меньше дискового пространства нужно для хранения данных. Размер единицы сжатия, равный l6 кластерам, основан на компромиссе между минимизацией размера сжатых файлов и замедлением операций чтения для программ, использующих прямой (произвольный) доступ к содержимому файлов. При каждом промахе кэша приходится декомпрессировать эквивалент l6 кластеров (вероятность промаха кэша при прямом доступе к файлу выше, чем при последовательном). Ha рис. 12–40 представлена запись MFT для сжатого файла, показанного на рис. 12–39.
Одно из различий между этим сжатым файлом и сжатым разреженным файлом из более раннего примера в том, что в данном случае три группы имеют длину менее 16 кластеров. Считывание этой информации из записи MFT позволяет NTFS определить, сжаты ли данные в этом файле. Каждая группа короче l6 кластеров содержит сжатые данные, которые NTFS должна разархивировать при первом чтении группы в кэш. Группа, длина которой равна точно 16 кластерам, не содержит сжатых данных, а значит, не требует декомпрессии.
Если группа содержит сжатые данные, NTFS разархивирует их во временный буфер и копирует в буфер вызывающей программы. Кроме того, NTFS помещает декомпрессированные данные в кэш, поэтому последующее чтение из этой группы выполняется так же быстро, как и простое чтение из кэша. Все изменения файла NTFS записывает в кэш, позволяя подсистеме отложенной записи асинхронно сжимать и записывать измененные данные на диск. Такая стратегия гарантирует, что запись в сжатый фарш вызовет примерно ту же задержку, что и запись в несжатый файл.
NTFS размещает сжатый файл на диске по возможности в смежных областях. Как указывают LCN, первые две группы сжатого файла на рис. 12–38 являются физически смежными, равно как и две последних. Если две и более группы расположены последовательно, NTFS выполняет опережающее чтение с диска — как и в случае обычных файлов. Поскольку чтение и декомпрессия непрерывных файловых данных выполняются асинхронно и еще до того, как программа запросит эти данные, то в последующих операциях чтения информация извлекается непосредственно из кэша, что значительно ускоряет процесс чтения.
Разреженные файлы
Разреженные файлы (тип файлов NTFS отличающийся от ранее описанных файлов, которые содержат разреженные данные) по сути являются сжатыми файлами, неразреженные данные которых NTFS не сжимает. Однако NTFS обрабатывает данные группы из записи MFT разреженного файла так же, как и в случае сжатых файлов, состоящих из разреженных и неразреженных данных.
Файл журнала изменений
Файл журнала изменений, $Extend$UsnJrnl, является разреженным файлом, который NTFS создает, только когда приложение активизирует регистрацию изменений. Журнал хранит записи изменений в потоке данных $J. Эти записи включают следующую информацию об изменениях файлов или каталогов:
• время изменения;
• тип изменения (удаление, переименование, увеличение размера и т. д.);
• атрибуты файла или каталога; • имя файла или каталога;
• номер файловой ссылки файла или каталога;
• номер файловой ссылки родительского каталога файла.
Поскольку журнал является разреженным, он никогда не переполняется; когда его размер на диске достигает определенного максимума, NTFS начинает просто обнулять файловые данные, предшествующие текущему блоку информации об изменениях, как показано на рис. 12–41. Ho, чтобы предотвратить постоянное изменение размера журнала, NTFS уменьшает его, только когда он в два раза превосходит установленный максимум.
Рис. 12–41. Выделение пространства для журнала изменений ($UsnJrnl)
Индексация
B NTFS каталог — это просто индекс имен файлов, т. е. совокупность имен файлов (с соответствующими файловыми ссылками), организованная таким образом, чтобы обеспечить быстрый доступ. Для создания каталога NTFS индексирует атрибуты «имя файла» из этого каталога. Запись MFT для корневого каталога тома показана на рис. 12–42.
C концептуальной точки зрения, элемент MFT для каталога содержит в своем атрибуте «корень индекса» отсортированный список файлов каталога. Ho для больших каталогов имена файлов на самом деле хранятся в индексных буферах размером по 4 Кб, которые содержат и структурируют имена файлов. Индексные буферы реализуют структуру данных типа «b+ tree», которая позволяет свести к минимуму число обращений к диску при поиске какого-либо файла, особенно в больших каталогах. Атрибут «корень индекса» содержит первый уровень структуры b+ tree (подкаталоги корневого каталога) и указывает на индексные буферы, содержащие следующий уровень (другие подкаталоги или файлы).
Ha рис. 12–42 в атрибуте «корень индекса» и индексных буферах показаны только имена файлов (например, файл 6), но каждая запись индекса содержит и файловую ссылку на запись MFT, описывающую данный файл, плюс метку времени и информацию о размере файла. NTFS дублирует метку времени и информацию о размере файла из записи MFT для файла. Такой подход, используемый файловыми системами FAT и NTFS, требует записи обновленной информации в два места. Ho даже при этом просмотр каталогов существенно ускоряется, поскольку файловая система может сообщать метки времени и размеры файлов, не открывая каждый файл в каталоге.
Атрибут «выделенная группа индексов» сопоставляет VCN групп индексных буферов с LCN, которые указывают, в каком месте диска находятся индексные буферы, а битовая карта используется для учета того, какие VCN в индексных буферах заняты, а какие свободны. Ha рис. 12–42 на каждый VCN, т. е. на каждый кластер, приходится по одной записи для файла, но на самом деле кластер содержит несколько записей. Каждый индексный буфер размером 4 Кб может содержать 20–30 записей для имен файлов.
Структура данных b+ tree — это разновидность сбалансированного дерева, идеальная для организации отсортированных данных, хранящихся на диске, так как позволяет минимизировать количество обращений к диску при поиске заданного элемента. B MFT атрибут корня индекса для каталога содержит несколько имен файлов, выступающих в качестве индексов для второго уровня b+ tree. C каждым именем файла в атрибуте корня индекса связан необязательный указатель индексного буфера. Этот индексный буфер содержит имена файлов, которые с точки зрения лексикографии меньше данного имени. Например, на рис. 12–42 файл 4 — это элемент первого уровня b+ tree. Он указывает на индексный буфер, содержащий имена файлов, которые лексикографически меньше имени в этом элементе, — файл 0, файл 1 и файл 3. Обратите внимание, что использованные в этом примере имена (файл1, файл2 и др.) не являются буквальными, — они просто иллюстрируют относительное размещение файлов, лексикографически упорядоченных в соответствии с показанной последовательностью.