PC Magazine/RE logo
©СК Пресс 1/97
e-mail: pcmagedt@aha.ru

PC Magazine, June 25, 1996, p. 217

Как Windows 95 хранит длинные имена файлов

Джефф Просис


В чем смысл длинных имен файлов для пользователей?

В течение долгих лет пользователи DOS и Windows испытывали неудобства, связанные с тем, что имена файлов не могли иметь длину более восьми символов плюс три символа на расширение. В операционных системах дл Macintosh, в OS/2 и Windows NT длинные имена предусмотрены, кажется, уже целую вечность. Однако почитатели Windows получили такую возможность лишь в прошлом году с выходом Windows 95; наконец-то можно спокойно расстаться с прежним форматом 8.3.

В литературе не раз упоминалось о том, что в файловой системе для Windows 95 - VFAT (Virtual File Allocation Table) - допустимы длинные имена. Однако известно ли вам, каким образом это реализовано? Структура записи для хранения на диске файлов с именами в формате 8.3 хорошо документирована. А вот об особенностях хранения длинных имен сообщаетс поразительно мало. Это несправедливо: чтобы обеспечить совместимость VFAT с ее предшественником - файловой системой FAT, - разработчики были вынуждены пойти на некоторые компромиссы, касающиеся структуры имен, и пользователям придется считаться с этим. Например, знаете ли вы о том, что существуют ограничения на употребление длинных имен файлов в корневом каталоге диска? Или о том, что, если не проводить регулярно дефрагментацию диска, содержащего файлы с длинными именами, может оказаться, что значительное пространство на нем пропадет впустую.

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

Формат каталога для имени файла в формате 8.3

Формат хранения коротких имен в Windows 95 тот же (8.3), что в DOS и 16 разрядных версиях Windows. Каждому файлу на любом диске соответствует 32-байт элемент каталога, содержащий имя файла, его атрибуты (скрытый, системный, только для чтения и т.д.), дату и время, а также прочую информацию. Когда вы набираете команду DIR для просмотра некоторого каталога, на экран выводится информация из таких элементов в удобной дл чтения форме.

На рис. 1 представлен элемент каталога в формате 8.3. Первые 11 байт заняты восьмисимвольным именем файла и трехсимвольным расширением. В эти пол помещаются 8 разрядные ASCII-коды соответствующих символов. Если длина имени менее восьми символов, а расширение менее трех символов, то оставшаяся часть заполняется пробелами (код ASCII - 32). Следующий байт отводится под битовые флажки - атрибуты файла. В последних 10 байт элемента каталога хранятся: дата и время создания или последнего изменения файла; номер его начального кластера и длина файла в байтах. Номер начального кластера - это 16-бит значение, обозначающее первый кластер цепочки, где записано содержащей файла.

Перед тем как прочитать или записать файл, ОС сверяется с соответствующей записью каталога, чтобы выяснить номер начального кластера. Если под текущий файл отведено на диске более одного кластера, то номера остальных извлекаются из находящейся на диске структуры, именуемой таблицей размещения файлов, или FAT (file allocation table).

Информация о файлах корневого каталога размещается в некоторой фиксированной специально для этого области на диске. Подчиненные каталоги представляют собой особые файлы, в записи в каталоге высшего уровня для которых четвертый бит байта атрибутов указывает на то, что это подкаталоги. Размер области на диске, отведенной под элементы корневого каталога, фиксирован и задается при форматировании диска; он не может быть изменен без применения специального программного обеспечения. Именно по этой причине максимальное число файлов и подкаталогов корневого каталога всегда ограничено (дл большинства жестких дисков - 512). Число же записей в подчиненных каталогах, как, впрочем, и размер файлов для их описания, не ограничено. Единственный, влияющий на количество файлов и подкаталогов фактор - наличие свободного пространства на диске.

Рис. 1. Формат хранения на диске коротких имен файлов длиной 32 байт.
Элемент каталога для короткого имени Время создания или последнего изменения файла (2 байт) Биты 0-4: Число секунд, деленное Атрибуты файла (1 байт) на 2 (0-29) Бит 0: Только для чтения Биты 5-10: Минуты (0-59) Бит 1: Скрытый Биты 11-15: Часы (0-23) Бит 2: Системный | Дата создания или последнего Бит 3: Метка тома | изменения файла (2 байт) Бит 4: Подкаталог | Биты 0-4: День месяца (0-31) Бит 5: Архивный | Биты 5-10: Месяц (1-12) Бит 6: Зарезервировано | Биты 11-15: Год (относительно Бит 7: Зарезервировано | 1980) | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Зарезервировано | | 8 символов для | (10 байт) | Размер файла (4 байт) имени файла | | (8 байт) 3 символа Номер начального для расширения кластера (2 байт) файла (3 байт)

Каталог для хранения длинных имен файлов

Дополнение ОС, работающей с именами файлов формата 8.3, возможностями использования длинных имен файлов не означает лишь просто увеличение размера элементов каталога для размещения более 11 символов, поскольку необходима совместимость и с предыдущими версиями. Если в новой ОС записи каталога будут представлены в новом формате, то, переписав файл на гибкий диск под управлением новой системы, вы не сможете прочитать его с помощью старой. Имеется и другая проблема. Если нова ОС будет передавать старым прикладным системам, рассчитанным на прием имен с длиной не более 11 символов, 255-символьные имена, программы ее "не поймут" будут происходить сбои. В чем причина? В программе для хранения считываемых имен файлов выделяется некоторая область памяти; если для этих целей предусматривается 16 байт, а ОС пересылает по названному адресу 32 символа, которые наложатс запишутся на другую информацию. Любой программист может сказать, что наилучший способ навредить программе - записать что-то чужое в ее область данных.

Для решения проблемы использования длинных имен при соблюдении полной совместимости со старыми версиями прикладных программ, подготовленными для DOS и Windows, разработчики Windows 95 нашли решение. Как правило, прикладные программы (за исключением специальных утилит, использующих для обращения к диску операции низкого уровня - например, Norton Disk Doctor) обращаются к ОС за именами файлов и каталогов не путем прямого считывания с диска соответствующих записей, а через специальные, встроенные в ОС функции. В результате тестирования специалистами Microsoft обнаружено, что, если у некоторого элемента каталога установлена "нереальная" комбинация битов атрибутов: "только для чтения", "скрытый", "системный", "метка тома" - другими словами, если байту атрибутов некоторого элемента каталога присвоить значение 0Fh, - тогда любые функции имеющиеся во всех существующих версиях DOS и Windows (предшествующих Windows 95), не "заметят" такого элемента каталога, словно его нет.

В итоге для Windows 95 проблема была решена следующим образом: для каждого файла и подкаталога имеются два имени: короткое, "понятное" всем прикладным программам, и длинное - для приложений Windows 95 и тех программ, в которых предусмотрена возможность работы с длинными именами. Для хранения коротких имен в формате 8.3 используются обычные 32-байт записи. Короткие имена Windows создает из длинных имен, отсекая шесть старших символов и добавляя в конце этого базового имени "1". Если же существует еще одно имя, состоящее из тех же шести символов, то этот номер увеличивается на единицу. Расширение файла сохраняется прежним. Если в имени встречается символ, не допустимый в предыдущих версиях Windows и DOS, он заменяется на знак "подчеркивание" (_).

Длинные имена (LFN) хранятся в специально отформатированных 32-байт записях, байт атрибутов у которых равен 0Fh. Для конкретного файла или подкаталога непосредственно перед его единственной записью каталога с его именем в формате 8.3 находитс группа из одной или нескольких записей, представляющих длинное имя. Каждая такая запись содержит часть длинного имени файла не более 13 символов, и ОС составляет полное длинное имя из всех записей.

Какие из этого следуют выводы? Если файл с длинным именем записать на гибкий диск, а затем прочитать его на компьютере, работающем под управлением DOS или Windows 3.x, то ОС распознает лишь короткое имя файла и проигнорирует все записи каталога для длинного имени. А поскольку в данном случае ОС "понятно" лишь короткое имя, прикладная программа, запросившая у нее имя файла или подкаталога, не получит неожиданно длинное имя. Все великолепно сходится.

В Windows 95 прикладным программам для 16 разрядных систем DOS и Windows, как и прежде, "видны" лишь короткие имена файлов, поскольку в ответ на их запросы ОС передает имена файлов и подкаталогов в формате 8.3. Чтобы "добраться" до длинных имен, программа должна обратиться к системным специальным функциям. Во всех прикладных программах для 32 разрядной версии Windows эти функции вызываются по умолчанию, поэтому они автоматически получают доступ к длинным именам.

На рис. 2 показана структура записи каталога дл длинного имени файла. Эти имена хранятся в формате Unicode, т. е. для каждого символа выделяется 2 байт (в отличие от ASCII, где лишь 1 байт). Символы, из которых состоит имя файла, распределяются по трем отдельным полям: первое - длиной 10 байт (5 символов), второе - 12 байт (6 символов) и третье - 4 байт (2 символа). В младших пяти битах первого байта записи содержитс порядковый номер, указывающий позицию данной записи каталога относительно остальных элементов, представляющих длинное имя данного файла. Например, если для записи длинного имени требуется три элемента каталога, то для первого из них порядковый номер будет равен 1, для второго - 2, для третьего - 3. Шестой бит первого байта третьего элемента задается равным 1, что означает, что текущий элемент - последний в цепочке.

Положение поля атрибутов в записях каталога как дл длинных имен, так и формата 8.3 одинаково. Объясняетс это тем, что, до тех пор пока файловая система не ознакомится с содержимым байта атрибутов, она не "знает", с каким типом записи она имеет дело в данный момент. Поле с номером начального кластера также находится на прежнем месте, однако в записях каталога для длинных имен его значение всегда равно 0. Поле с указанием типа также содержит 0; это наблюдалось во всех рассмотренных мною вариантах длинных имен. Хотя в книге Inside Windows 95 by Adrian King (Microsoft Press) (Адриан Кинг, Windows 95 изнутри/Перев. с англ. - СПб.: "Питер", 1995. - Прим. перев.) упоминается о том, что в данном поле может быть и ненулевое значение, свидетельствующее, что в данной записи каталога содержится "сведения о классе" для соответствующего файла. (К сожалению, в книге не сообщается, что это за информация о классе. Остается лишь догадываться, что в Microsoft имели в виду.) Байт с 8 бит контрольной суммой для длинного имени рассчитывается как остаток от деления на 256 суммы значений определенных полей соответствующей записи в каталоге формата 8.3. В Windows 95 контрольная сумма используется для выявлени "осиротевших" или испорченных записей в каталоге дл длинных имен.

Рис. 2. Длинные имена файлов хранятся на диске в указанном формате и размещаются в одном или нескольких 32-байт элементах каталога перед элементами каталога для коротких имен. Символы, составляющие имя файла, представлены в кодах Unicode, т. е. на каждый из них по 2 байта.
Элемент каталога для длинного имени Порядок следования (1 байт) Биты 0-4: Порядковый номер (1-31) Бит 5: По видимому, не используется (всегда 0) Бит 6: 1=конечный элемент текущего длинного имени Бит 7: По видимому, не используется (всегда 0) | Номер начального кластера | (2 байт, всегда 0) | | | Первые пять символов Следующие шесть символов| Следующие два символа | длинного имени (10 байт) длинного имени (12 байт)| длинного имени | | | | | (4 байт) | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Контрольная сумма (1 байт) | Указатель типа (1 байт, всегда 0) Атрибуты файла (1 байт, всегда 0Fh)

Формирование записи для длинного имени происходит даже в том случае, если оно достаточно коротко и годится для формата 8.3, поскольку для него предусматривается регистр, а для короткого - нет. На рис. 3 показано шестнадцатеричное представление элементов каталога для файла с именем Budget.xls. Короткое имя (BUDGET.XLS) заносится в запись формата 8.3. Непосредственно перед ней располагается запись дл длинного имени, содержащая имя Budget.xls. Порядковый номер данного элемента каталога длинного имени равен 1, шестой бит - также 1, что означает, что текущий элемент не только первый, но и последний. Поскольку записи в каталоге для длинного имени всегда размещаютс непосредственно перед соответствующим элементом каталога формата 8.3, Windows 95, обнаружив дл требуемого файла или подкаталога элемент каталога в формате 8.3, легко находит его длинное имя.

Рис. 3. Шестнадцатиричное представление элементов каталога для файла с именем Budget.xls
41 42 00 75 00 64 00 67-00 65 00 0F 00 D8 74 00 AB.u.d.g.e....t. 2E 00 78 00 6C 00 73 00-00 00 00 00 FF FF FF FF ..x.l.s......... 42 55 44 47 45 54 20 20-58 4C 53 20 00 96 34 87 BUDGET XLS ..4. 70 20 70 20 00 00 54 48-70 20 C9 03 A9 1D 00 00 p p ..THp ......

Рис. 4 иллюстрирует, как бы выглядели элементы каталога для короткого и длинного имени файла, если вместо Budget.xls его назвать Budget for Fiscal Year 1996.xls. Поскольку в этом случае длинное имя состоит из 31 символа, потребуется 3 записи для длинного имени. Обратите внимание на обратный порядок положени элементов: запись с первыми 13 символами длинного имени помещается непосредственно перед коротким именем, следующие 13 символов - перед этой записью; и наконец, в самом начале идет запись, содержащая последние пять символов.

Рис. 4. Шестнадцатиричное представление элементов каталога для файла с именем Budget for Fiscal Year 1996.xls "Подводные камни" механизма длинных имен
43 36 00 2E 00 78 00 6C-00 73 00 0F 00 E0 00 00 C6...x.l.s...... FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................ 02 73 00 63 00 61 00 6C-00 20 00 0F 00 E0 59 00 .s.c.a.l. .. .y. 65 00 61 00 72 00 20 00-31 00 00 00 39 00 39 00 e.a.r. .1...9.9. 01 42 00 75 00 64 00 67-00 65 00 0F 00 D8 74 00 .B.u.d.g.e....t. 20 00 66 00 6F 00 72 00-20 00 00 00 46 00 69 00 .f.o.r. ....F.i. 42 55 44 47 45 54 7E 31-58 4C 53 20 00 4A CF 88 BUDGET~1XLS .J.. 70 20 70 20 00 00 54 48-70 20 C9 03 A9 1D 00 00 p p ..THp ......

"Подводные камни" механизма длинных имен

На первый взгляд предложенный VFAT механизм дл длинных имен файлов позволяет сохранить преемственность с прикладными программами прошлого поколения и выглядит идеальным. Однако этот метод далек от совершенства. Объясним почему.

Одна из проблем, присущих использованию длинных имен, заключается в том, что для них требуется больше дискового пространства, чем для коротких имен. Это не имеет существенного значения при хранении длинных имен в подчиненных каталогах, поскольку по мере добавления в каталоги новых записей последние могут расширяться. Однако максимальное число записей в корневом каталоге ограниченно, а длинные имена файлов занимают в нем страшно много места. Для большинства жестких дисков в корневом каталоге может содержаться не более 512 записей. Например, для хранения имени из 128 символов потребуется 11 записей (десять для длинного имени и один - для короткого). Поэтому в корневом каталоге удастся разместить лишь 46 файлов и подкаталогов, если название каждого из них состоит из 128 символов. При использовании длинных имен файлов в корневых каталогах дисков, отформатированных для более совершенных файловых систем, таких, как HPFS в OS/2 или NTFS в Windows NT, подобной проблемы не возникает, поскольку размер корневых каталогов в них не ограничен.

Более серьезная проблема возникает в том случае, когда элементы каталога длинных имен становятс "сиротами". Допустим, вы переписали некоторый файл на гибкий диск, а затем работали с ним на компьютере под управлением DOS или Windows 3.1. Если там удалить или переименовать этот файл, то будет удалена или переименована соответствующая запись для формата 8.3. Однако записи для длинных имен останутся нетронутыми, поскольку ни DOS, ни Windows 3.1 не подозревают об их существовании. Такие записи оказываются "осиротевшими". (Конечно, аналогичные "осиротевшие" записи для длинных имен могут образоваться и на жестком диске, если загрузить систему с дискеты, где содержится DOS, и удалить или переименовать файлы на жестком диске.)

Windows 95 обнаруживает подобные элементы каталога, так как их контрольная сумма больше не соответствует тому, что записано в последующей записи каталога формата 8.3. Однако, насколько я знаю, такие записи не удаляются автоматически. Они остаются на месте, занима дисковое пространство, до тех пор пока вы не запустите программу ScanDisk. Эта утилита отыскивает "осиротевшие" записи и запрашивает разрешени пользователя на их удаление.

А как обстоят дела с 16 разрядными программами, работающими под управлением Windows 95? Безопасно ли удаление или переименование файлов с их помощью? К чести Windows 95 она способна "уловить" момент, когда некоторая программа прошлого поколения, не обладающа инструментами работы с длинными именами, производит удаление или переименование файла. В обоих случаях ОС удаляет записи для длинного имени, т. е. они не остаются "осиротевшими". Таким образом, если стара программа переименовывает файл (используя его короткое имя), то исчезает и его длинное имя. Учитывая это, лучше избегать использования длинных имен, если дл управления файлами или каталогами вы все еще пользуетесь привычными программами DOS, ориентированными на Windows 3.1.

Однако даже если у вас в работе только 32 разрядные программы, могут возникнуть ситуации, когда применение длинных имен приводит к неэффективному использованию пространства на диске. По мере создания и удалени файлов в некотором каталоге записи внем становятс "фрагментированными", т. е. действительные записи перемежаются с аннулированными. Поскольку относящиеся к конкретному файлу или каталогу записи для длинного имени и формата 8.3 должны находиться рядом, может случиться так, что в практически пустом каталоге не найдется места для размещения нового длинного имени файла. Причина в том, что в каталоге не будет непрерывной, достаточной по размеру свободной области. Так, если в самой большой группе последовательно расположенных, незанятых записей их три, а вы создаете файл, для имени которого требуется четыре, тогда эта операция либо заканчивается сообщением об ошибке (если файл создается в корневом каталоге), либо ОС выделит дополнительное пространство для новых четырех записей каталога (если файл добавляется в подчиненный каталог).

В любом случае получается, что часть пространства на диске расходуется напрасно, поскольку свободные записи остаются неиспользованными. Хуже, если между рабочими записями оказывается "зажатой" одинокая свободна запись каталога. Единственная возможность когда-либо воспользоваться этим элементом (предположим, что окружающие ее записи не высвобождаются) - это если некоторая прикладная программа прошлых поколений создает файл или подкаталог и при этом случайно будет задействован именно данная запись каталога (для файлов или каталогов, создаваемых программами для прежних версий ОС, требуется лишь один элемент каталога, поскольку эти ОС не формируют длинных имен файлов).

Единственный выход из создавшейся ситуации - дефрагментация диска. Утилита Defrag, входящая в состав Windows 95, производит упаковку рабочих записей в каталоге, объединяя свободные записи в единую область. Советую вам регулярно проводить дефрагментацию своих дисков, тем более если вы работаете с длинными именами.

Знать заранее - значит быть во всеоружии

Теперь, когда вы разобрались, как в Windows 95 реализован механизм обработки длинных имен, вам будет легче избегать всяких неприятностей. Короче говоря, вы получите максимум возможного от этого механизма, если будете использовать главным образом 32 разрядные программы, регулярно запускать на исполнение Defrag и ScanDisk и избегать использования без необходимости длинных имен для файлов из корневого каталога.

Возможно, механизм VFAT по обслуживанию длинных имен не слишком совершенен. Однако все же это великое достижение по сравнению с именами в формате 8.3, с которым мы имели дело до сих пор.