Рядовому пользователю компьютерных электронных устройств редко, но приходится сталкиваться с таким понятием, как «выбор файловой системы». Чаще всего это происходит при необходимости форматирования внешних накопителей (флешек, microSD), установке операционных систем, восстановлении данных на проблемных носителях, в том числе жестких дисках. Пользователям Windows предлагается выбрать тип файловой системы, FAT32 или NTFS, и способ форматирования (быстрое/глубокое). Дополнительно можно установить размер кластера. При использовании ОС Linux и macOS названия файловых систем могут отличаться.
Возникает логичный вопрос: что такое файловая система и в чем ее предназначение? В данной статье дадим ответы на основные вопросы касательно наиболее распространенных ФС.
Что такое файловая система
Обычно вся информация записывается, хранится и обрабатывается на различных цифровых носителях в виде файлов. Далее, в зависимости от типа файла, кодируется в виде знакомых расширений – *exe, *doc, *pdf и т.д., происходит их открытие и обработка в соответствующем программном обеспечении. Мало кто задумывается, каким образом происходит хранение и обработка цифрового массива в целом на соответствующем носителе.
Операционная система воспринимает физический диск хранения информации как набор кластеров размером 512 байт и больше. Драйверы файловой системы организуют кластеры в файлы и каталоги, которые также являются файлами, содержащими список других файлов в этом каталоге. Эти же драйверы отслеживают, какие из кластеров в настоящее время используются, какие свободны, какие помечены как неисправные.
Запись файлов большого объема приводит к необходимости фрагментации, когда файлы не сохраняются как целые единицы, а делятся на фрагменты. Каждый фрагмент записывается в отдельные кластеры, состоящие из ячеек (размер ячейки составляет один байт). Информация о всех фрагментах, как части одного файла, хранится в файловой системе.
Файловая система связывает носитель информации (хранилище) с прикладным программным обеспечением, организуя доступ к конкретным файлам при помощи функционала взаимодействия программ API. Программа, при обращении к файлу, располагает данными только о его имени, размере и атрибутах. Всю остальную информацию, касающуюся типа носителя, на котором записан файл, и структуры хранения данных, она получает от драйвера файловой системы.
На физическом уровне драйверы ФС оптимизируют запись и считывание отдельных частей файлов для ускоренной обработки запросов, фрагментации и «склеивания» хранящейся в ячейках информации. Данный алгоритм получил распространение в большинстве популярных файловых систем на концептуальном уровне в виде иерархической структуры представления метаданных (B-trees). Технология снижает количество самых длительных дисковых операций – позиционирования головок при чтении произвольных блоков. Это позволяет не только ускорить обработку запросов, но и продлить срок службы HDD. В случае с твердотельными накопителями, где принцип записи, хранения и считывания информации отличается от применяемого в жестких дисках, ситуация с выбором оптимальной файловой системы имеет свои нюансы.
Комьюнити теперь в Телеграм
Подпишитесь и будьте в курсе последних IT-новостей
Подписаться
Основные функции файловых систем
Файловая система отвечает за оптимальное логическое распределение информационных данных на конкретном физическом носителе. Драйвер ФС организует взаимодействие между хранилищем, операционной системой и прикладным программным обеспечением. Правильный выбор файловой системы для конкретных пользовательских задач влияет на скорость обработки данных, принципы распределения и другие функциональные возможности, необходимые для стабильной работы любых компьютерных систем. Иными словами, это совокупность условий и правил, определяющих способ организации файлов на носителях информации.
Основными функциями файловой системы являются:
- размещение и упорядочивание на носителе данных в виде файлов;
- определение максимально поддерживаемого объема данных на носителе информации;
- создание, чтение и удаление файлов;
- назначение и изменение атрибутов файлов (размер, время создания и изменения, владелец и создатель файла, доступен только для чтения, скрытый файл, временный файл, архивный, исполняемый, максимальная длина имени файла и т.п.);
- определение структуры файла;
- поиск файлов;
- организация каталогов для логической организации файлов;
- защита файлов при системном сбое;
- защита файлов от несанкционированного доступа и изменения их содержимого.
Задачи файловой системы
Функционал файловой системы нацелен на решение следующих задач:
- присвоение имен файлам;
- программный интерфейс работы с файлами для приложений;
- отображение логической модели файловой системы на физическую организацию хранилища данных;
- поддержка устойчивости файловой системы к сбоям питания, ошибкам аппаратных и программных средств;
- содержание параметров файла, необходимых для правильного взаимодействия с другими объектами системы (ядро, приложения и пр.).
В многопользовательских системах реализуется задача защиты файлов от несанкционированного доступа, обеспечение совместной работы. При открытии файла одним из пользователей для других этот же файл временно будет доступен в режиме «только чтение».
Вся информация о файлах хранится в особых областях раздела (томах). Структура справочников зависит от типа файловой системы. Справочник файлов позволяет ассоциировать числовые идентификаторы уникальных файлов и дополнительную информацию о них с непосредственным содержимым файла, хранящимся в другой области раздела.
Операционные системы и типы файловых систем
Существует три основных вида операционных систем, используемых для управления любыми информационными устройствами: Windows компании Microsoft, macOS разработки Apple и операционные системы с открытым исходным кодом на базе Linux. Все они, для взаимодействия с физическими носителями, используют различные типы файловых систем, многие из которых дружат только со «своей» операционкой. В большинстве случаев они являются предустановленными, рядовые пользователи редко создают новые дисковые разделы и еще реже задумываются об их настройках.
В случае с Windows все выглядит достаточно просто: NTFS на всех дисковых разделах и FAT32 (или NTFS) на флешках. Если установлен NAS (сервер для хранения данных на файловом уровне), и в нем используется какая-то другая файловая система, то практически никто не обращает на это внимания. К нему просто подключаются по сети и качают файлы.
На мобильных гаджетах с ОС Android чаще всего установлена ФС версии ext4 во внутренней памяти и FAT32 на карточках microSD. Владельцы продукции Apple зачастую вообще не имеют представления, какая файловая система используется на их устройствах – HFS+, HFSX, APFS, WTFS или другая. Для них существуют лишь красивые значки папок и файлов в графическом интерфейсе.
Более богатый выбор у линуксоидов. Но здесь настройка и использование определенного типа файловой системы требует хотя бы минимальных навыков программирования. Тем более, мало кто задумывается, можно ли использовать в определенной ОС «неродную» файловую систему. И зачем вообще это нужно.
Рассмотрим более подробно виды файловых систем в зависимости от их предпочтительного использования с определенной операционной системой.
Файловые системы Windows
Исходный код файловой системы, получившей название FAT, был разработан по личной договоренности владельца Microsoft Билла Гейтса с первым наемным сотрудником компании Марком Макдональдом в 1977 году. Основной задачей FAT была работа с данными в операционной системе Microsoft 8080/Z80 на базе платформы MDOS/MIDAS. Файловая система FAT претерпела несколько модификаций – FAT12, FAT16 и, наконец, FAT32, которая используется сейчас в большинстве внешних накопителей. Основным отличием каждой версии является преодоление ограниченного объема доступной для хранения информации. В дальнейшем были разработаны еще две более совершенные системы обработки и хранения данных – NTFS и ReFS.
FAT (таблица распределения файлов)
Числа в FAT12, FAT16 и FAT32 обозначают количество бит, используемых для перечисления блока файловой системы. FAT32 является фактическим стандартом и устанавливается на большинстве видов сменных носителей по умолчанию. Одной из особенностей этой версии ФС является возможность применения не только на современных моделях компьютеров, но и в устаревших устройствах и консолях, снабженных разъемом USB.
Пространство FAT32 логически разделено на три сопредельные области:
- зарезервированный сектор для служебных структур;
- табличная форма указателей;
- непосредственная зона записи содержимого файлов.
К недостатком стандарта FAT32 относится ограничение размера файлов на диске до 4 Гб и всего раздела в пределах 8 Тб. По этой причине данная файловая система чаще всего используется в USB-накопителях и других внешних носителях информации. Для установки последней версии ОС Microsoft Windows 10 на внутреннем носителе потребуется более продвинутая файловая система.
С целью устранения ограничений, присущих FAT32, корпорация Microsoft разработала обновленную версию файловой системы exFAT (расширенная таблица размещения файлов). Новая ФС очень схожа со своим предшественником, но позволяет пользователям хранить файлы намного большего размера, чем четыре гигабайта. В exFAT значительно снижено число перезаписей секторов, ответственных за непосредственное хранение информации. Функция очень важна для твердотельных накопителей ввиду необратимого изнашивания ячеек после определенного количества операций записи. Продукт exFAT совместим с операционными системами Mac, Android и Windows. Для Linux понадобится вспомогательное программное обеспечение.
NTFS (файловая система новой технологии)
Стандарт NTFS разработан с целью устранения недостатков, присущих более ранним версиям ФС. Впервые он был реализован в Windows NT в 1995 году, и в настоящее время является основной файловой системой для Windows. Система NTFS расширила допустимый предел размера файлов до шестнадцати гигабайт, поддерживает разделы диска до 16 Эб (эксабайт, 1018 байт). Использование системы шифрования Encryption File System (метод «прозрачного шифрования») осуществляет разграничение доступа к данным для различных пользователей, предотвращает несанкционированный доступ к содержимому файла. Файловая система позволяет использовать расширенные имена файлов, включая поддержку многоязычности в стандарте юникода UTF, в том числе в формате кириллицы. Встроенное приложение проверки жесткого диска или внешнего накопителя на ошибки файловой системы chkdsk повышает надежность работы харда, но отрицательно влияет на производительность.
ReFS (Resilient File System)
Последняя разработка Microsoft, доступная для серверов Windows 8 и 10. Архитектура файловой системы в основном организована в виде B + -tree. Файловая система ReFS обладает высокой отказоустойчивостью благодаря реализации новых функций:
- Copy-on-Write (CoW) – никакие метаданные не изменяются без копирования;
- данные записываются на новое дисковое пространство, а не поверх существующих файлов;
- при модификации метаданных новая копия хранится в свободном дисковом пространстве, затем система создает ссылку из старых метаданных на новую версию.
Все это позволяет повысить надежность хранения файлов, обеспечивает быстрое и легкое восстановление данных.
Файловые системы macOS
Для операционной системы macOS компания Apple использует собственные разработки файловых систем:
- HFS+, которая является усовершенствованной версией HFS, ранее применяемой на компьютерах Macintosh, и ее более соверешенный аналог APFS. Стандарт HFS+ используется во всех устройствах под управлением продуктов Apple, включая компьютеры Mac, iPod, а также Apple X Server.
- Кластерная файловая система Apple Xsan, созданная из файловых систем StorNext и CentraVision, используется в расширенных серверных продуктах. Эта файловая система хранит файлы и папки, информацию Finder о просмотре каталогов, положениях окна и т.д.
Файловые системы Linux
В отличие от ОС Windows и macOS, ограничивающих выбор файловой системы предустановленными вариантами, Linux предоставляет возможность использования нескольких ФС, каждая из которых оптимизирована для решения определенных задач. Файловые системы в Linux используются не только для работы с файлами на диске, но и для хранения данных в оперативной памяти или доступа к конфигурации ядра во время работы системы. Все они включены в ядро и могут использоваться в качестве корневой файловой системы.
Основные файловые системы, используемые в дистрибутивах Linux:
- Ext2;
- Ext3;
- Ext4;
- JFS;
- ReiserFS;
- XFS;
- Btrfs;
- ZFS.
Ext2, Ext3, Ext4 или Extended Filesystem – стандартная файловая система, первоначально разработанная еще для Minix. Содержит максимальное количество функций и является наиболее стабильной в связи с редкими изменениями кодовой базы. Начиная с ext3 в системе используется функция журналирования. Сегодня версия ext4 присутствует во всех дистрибутивах Linux.
JFS или Journaled File System разработана в IBM в качестве альтернативы для файловых систем ext. Сейчас она используется там, где необходима высокая стабильность и минимальное потребление ресурсов (в первую очередь в многопроцессорных компьютерах). В журнале хранятся только метаданные, что позволяет восстанавливать старые версии файлов после сбоев.
ReiserFS также разработана в качестве альтернативы ext3, поддерживает только Linux. Динамический размер блока позволяет упаковывать несколько небольших файлов в один блок, что предотвращает фрагментацию и улучшает работу с небольшими файлами. Недостатком является риск потери данных при отключении энергии.
XFS рассчитана на файлы большого размера, поддерживает диски до 2 терабайт. Преимуществом системы является высокая скорость работы с большими файлами, отложенное выделение места, увеличение разделов на лету, незначительный размер служебной информации. К недостаткам относится невозможность уменьшения размера, сложность восстановления данных и риск потери файлов при аварийном отключении питания.
Btrfs или B-Tree File System легко администрируется, обладает высокой отказоустойчивостью и производительностью. Используется как файловая система по умолчанию в OpenSUSE и SUSE Linux.
Другие ФС, такие как NTFS, FAT, HFS, могут использоваться в Linux, но корневая файловая система на них не устанавливается, поскольку они для этого не предназначены.
Дополнительные файловые системы
В операционных системах семейства Unix BSD (созданы на базе Linux) и Sun Solaris чаще всего используются различные версии ФС UFS (Unix File System), известной также под названием FFS (Fast File System). В современных компьютерных технологиях данные файловые системы могут быть заменены на альтернативные: ZFS для Solaris, JFS и ее производные для Unix.
Кластерные файловые системы включают поддержку распределенных хранилищ, расширяемость и модульность. К ним относятся:
- ZFS – «Zettabyte File System» разработана для распределенных хранилищ Sun Solaris OS;
- Apple Xsan – эволюция компании Apple в CentraVision и более поздних разработках StorNext;
- VMFS (Файловая система виртуальных машин) разработана компанией VMware для VMware ESX Server;
- GFS – Red Hat Linux именуется как «глобальная файловая система» для Linux;
- JFS1 – оригинальный (устаревший) дизайн файловой системы IBM JFS, используемой в старых системах хранения AIX.
Практический пример использования файловых систем
Владельцы мобильных гаджетов для хранения большого объема информации используют дополнительные твердотельные накопители microSD (HC), по умолчанию отформатированные в стандарте FAT32. Это является основным препятствием для установки на них приложений и переноса данных из внутренней памяти. Чтобы решить эту проблему, необходимо создать на карточке раздел с ext3 или ext4. На него можно перенести все файловые атрибуты (включая владельца и права доступа), чтобы любое приложение могло работать так, словно запустилось из внутренней памяти.
Операционная система Windows не умеет делать на флешках больше одного раздела. С этой задачей легко справится Linux, который можно запустить, например, в виртуальной среде. Второй вариант — использование специальной утилиты для работы с логической разметкой, такой как MiniTool Partition Wizard Free. Обнаружив на карточке дополнительный первичный раздел с ext3/ext4, приложение Андроид Link2SD и аналогичные ему предложат куда больше вариантов.
Флешки и карты памяти быстро умирают как раз из-за того, что любое изменение в FAT32 вызывает перезапись одних и тех же секторов. Гораздо лучше использовать на флеш-картах NTFS с ее устойчивой к сбоям таблицей $MFT. Небольшие файлы могут храниться прямо в главной файловой таблице, а расширения и копии записываются в разные области флеш-памяти. Благодаря индексации на NTFS поиск выполняется быстрее. Аналогичных примеров оптимизации работы с различными накопителями за счет правильного использования возможностей файловых систем существует множество.
Надеюсь, краткий обзор основных ФС поможет решить практические задачи в части правильного выбора и настройки ваших компьютерных устройств в повседневной практике.
Введение
Информация в информационных системах (ИС) возникает в процессе обработки хранящихся данных. На компьютерах, используемых для создания ИС, данные хранятся на постоянном запоминающем устройстве (ПЗУ) в виде именованных последовательностей, называемых файлами. Хранение файлов подобно хранению книг в библиотеке, и для организации доступа к ним требуется специальная система, обеспечивающая минимизацию времени доступа и удобство работы.
Файловая система представляет совокупность служебных структур на носителе и средств операционной системы, обеспечивающих манипуляцию файлами. (Исторически сложилось, что операционные системы семейства Windows развиваются в двух направлениях (Windows 95, Windows 98 и Windows Ме составляют одно направление, а Windows NT и Windows 2000 второе направление), предоставляющих различные средства для работы со служебными структурами и файлами).
Файловая система FAT (File Allocation Table) была разработана Биллом Гейтсом и Марком МакДональдом в 1977 году и первоначально использовалась в операционной системе 86-DOS. Чтобы добиться переносимости программ из операционной системы CP/M в 86-DOS, в ней были сохранены ранее принятые ограничения на имена файлов. В дальнейшем 86-DOS была приобретена Microsoft и стала основой для ОС MS-DOS 1.0, выпущенной в августе 1981 года. Эта файловая система была изначально создана для обеспечения произвольного доступа к файлам на гибких дисках относительно небольшого размера.
Сейчас существует четыре версии FAT — FAT8, FAT12, FAT16 и FAT32. Они отличаются разрядностью записей в дисковой структуре, то есть количеством бит, отведённых для хранения номера кластера. FAT12 применяется в основном для дискет, FAT16 — для дисков малого объёма, FAT32- для жестких дисков. На основе FAT была разработана новая файловая система exFAT (extended FAT), используемая преимущественно для флеш-накопителей.
Структура FAT
В файловой системе FAT дисковое пространство любого логического диска делится на две области:
- системную область и
- область данных.
Системная область создается и инициализируется при форматировании, а впоследствии обновляется при манипулировании файловой структурой.
Системная область состоит из следующих компонентов:
- загрузочного сектора, содержащего загрузочную запись (boot record);
- зарезервированных секторов (их может и не быть);
- таблицы размещения файлов (FAT, File Allocation Table);
- корневого каталога (Root directory, ROOT).
Эти компоненты расположены на диске друг за другом.
Область данных содержит файлы и каталоги, подчиненные корневому.
Область данных разбивают на так называемые кластеры. Кластер — это один или несколько смежных секторов области данных. С другой стороны, кластер — это минимальная адресуемая единица дисковой памяти, выделяемая файлу. Т.е. файл или каталог занимает целое число кластеров. Для создания и записи на диск нового файла операционная система отводит для него несколько свободных кластеров диска. Эти кластеры не обязательно должны следовать друг за другом. Для каждого файла хранится список всех номеров кластеров, которые предоставлены данному файлу.
Разбиение области данных на кластеры вместо использования секторов позволяет: - уменьшить размер таблицы FAT;
- уменьшить фрагментацию файлов;
- сокращается длина цепочек файла и ускоряется доступ к файлу.
Однако слишком большой размер кластера ведет к неэффективному использованию области данных, особенно в случае большого количества маленьких файлов (ведь на каждый файл теряется в среднем полкластера).
В современных файловых системах (FAT32, HPFS, NTFS) эта проблема решается за счет ограничения размера кластера (максимум 4 Кбайта)
Картой области данных является Таблица размещения файлов (File Allocation Table — FAT) Каждый элемент таблицы FAT (12, 16 или 32 бит) соответствует одному кластеру диска и характеризует его состояние: свободен, занят или является сбойным кластером (bad cluster).
- Если кластер распределен какому-либо файлу (т.е., занят), то соответствующий элемент FAT содержит номер следующего кластера файла;
- последний кластер файла отмечается числом в диапазоне FF8h — FFFh (FFF8h — FFFFh);
- если кластер является свободным, он содержит нулевое значение 000h (0000h);
- кластер, непригодный для использования (сбойный), отмечается числом FF7h (FFF7h).
Таким образом, в таблице FAT кластеры, принадлежащие одному файлу, связываются в цепочки.
Таблица размещения файлов хранится сразу после загрузочной записи логического диска, ее точное расположение описано в специальном поле в загрузочном секторе.
Она хранится в двух идентичных экземплярах, которые следуют друг за другом. При разрушении первой копии таблицы используется вторая.
В связи с тем, что FAT используется очень интенсивно при доступе к диску, она обычно загружается в ОП (в буфера ввода/вывода или кэш) и остается там настолько долго, насколько это возможно.
Для просмотра и редактирования таблицы FAT можно использовать утилиту Disk Editor.
Подробная информация о самом файле хранится в другой структуре, которая называется корневым каталогом. Каждый логический диск (Жесткий диск является физическим устройством, т.е. его можно физически установить, заменить или удалить.
Для удобства работы жесткий диск разбивают на логические диски, которые являются виртуальными и их нельзя, что называется, потрогать руками.
На одном жестком диске может быть:
• либо несколько логических дисков,
• либо один-единственный логический диск.)
имеет свой корневой каталог (ROOT, англ. — корень).
Корневой каталог описывает файлы и другие каталоги. Элементом каталога является дескриптор (описатель) файла.
Дескриптор каждого файла и каталога включает его
- имя
- расширение
- дату создания или последней модификации
- время создания или последней модификации
- атрибуты (архивный, атрибут каталога, атрибут тома, системный, скрытый, только для чтения)
- длину файла (для каталога — 0)
- зарезервированное поле, которое не используется
- номер первого кластера в цепочке кластеров, отведенных файлу или каталогу; получив этот номер, операционная система, обращаясь к таблице FAT, узнает и все остальные номера кластеров файла.
Итак, пользователь запускает файл на выполнение. Операционная система ищет файл с нужным именем, просматривая описания файлов в текущем каталоге. Когда найден требуемый элемент в текущем каталоге, операционная система считывает номер первого кластера данного файла, а затем по таблице FAT определяет остальные номера кластеров. Данные из этих кластеров считываются в оперативную память, объединяясь в один непрерывный участок. Операционная система передает управление файлу, и программа начинает работать.
Для просмотра и редактирования корневого каталога ROOT можно также использовать утилиту Disk Editor.
Разновидности FAT
Файловая система VFAT
Файловая система VFAT (виртуальная FAT) впервые появилась в Windows for Workgroups 3.11 и была предназначена для файлового ввода/вывода в защищенном режиме.
Используется эта файловая система в Windows 95.
Поддерживается она также и в Windows NT 4.
VFAT — это «родная» 32-разрядная файловая система Windows95. Ее контролирует драйвер VFAT.VXD.
VFAT использует 32-разрядный код для всех файловых операций, может использовать 32-разрядные драйверы защищенного режима.
НО, элементы таблицы размещения файлов остаются 12- или 16-разрядными, поэтому на диске используется та же структура данных (FAT). Т.е. формат таблицы VFAT такой же, как и формат FAT.
VFAT наряду с именами «8.3» поддерживает длинные имена файлов. (Часто говорят, что VFAT — это FAT с поддержкой длинных имен).
Основной недостаток VFAT — большие потери на кластеризацию при больших размерах логического диска и ограничения на сам размер логического диска.
Файловая система FAT32
Это новая реализация идеи использования таблицы FAT.
FAT32 — последняя версия файловой системы FAT и улучшение предыдущей версии, известной как FAT16. Она была создана, чтобы преодолеть ограничения на размер тома в FAT16, позволяя при этом использовать старый код программ MS-DOS и сохранив формат.
FAT32 — это полностью самостоятельная 32-разрядная файловая система.
Впервые использовалась в Windows OSR2 (OEM Service Release 2).
В настоящее время FAT32 используется в Windows 98 и Windows ME.
Она содержит многочисленные усовершенствования и дополнения по сравнению с предыдущими реализациями FAT.
- Намного эффективнее расходует дисковое пространство за счет того, что использует кластеры меньшего размера (4 Кб) — подсчитано, что экономится до 15%.
- Имеет расширенную загрузочную запись, которая позволяет создавать копии критических структур данных, что повышает устойчивость диска к нарушениям структур диска
- Может использовать резервную копию FAT вместо стандартной.
- Может перемещать корневой каталог, другими словами, корневой каталог может находиться в произвольном месте, что снимает ограничение на размер корневого каталога (512 элементов, т.к. ROOT должен был занимать один кластер).
- Усовершенствована структура корневого каталога
Появились дополнительные поля, например, время создания, дата создания, дата последнего доступа, контрольная сумма.
По-прежнему для длинного имени файла используется несколько дескрипторов.
exFAT
Обновленная файловая система созданная компанией microsoft на замену FAT32. Начала использоваться в Windows Vista SP1 и имеет максимальный размер файла 16 эксабайт (ЭБ), который равен 1 Эб = 1018 байтам. Совместима с Mac OS и Windows, является очень хорошей системой для обмена большими файлами.
Минусы:
• Она не имеет никакой функциональности журналирования, в которой все изменения файлов на диске, отмечены в журнале прежде, чем они на самом деле выполнены.
• Не поддерживается Time Machine в Apple. Одним словом, вы не сможете сделать резервную копию от Apple с помощью программного обеспечения Time Machine.
• Очень сложная структура, требующая больше вычислительных мощностей.
Плюсы:
• Перезаписывает меньшее количество раз один и тот же сектор, что важно для флешек, продлевая жизнь ячейкам памяти. Как известно флешки имеют N-количества перезаписей, потом выходят из строя.
• Большой лимит на размер файла 16 эксабайт.
• Размер кластера 32 мегабайта.
• Улучшено распределение свободного место, что уменьшает дефрагментацию
Достоинства и недостатки FAT
Достоинства FAT:
- для эффективной работы требуется немного оперативной памяти;
- быстрая работа с малыми и средними каталогами;
- меньшее перемещение головок;
- эффективная работа на медленных дисках.
Недостатки FAT: - большая потеря быстродействия с увеличением фрагментации;
- сложность с произвольным доступом к большим файлам;
- очень медленная работа с каталогами, содержащими большое количество файлов. При создании файла работает правило — выделяется первый свободный кластер. Это ведет к фрагментации диска и сложным цепочкам файлов. Отсюда следует замедление работы с файлами.
Рубрика: Администрирование / Архитектура |
Мой мир Вконтакте Одноклассники Google+ |
ВЛАДИМИР МЕШКОВ
Архитектура файловой системы FAT
Общая характеристика файловой системы FAT. Структура раздела с файловой системой FAT
Файловая система FAT (File Allocation Table) была разработана Биллом Гейтсом и Марком Макдональдом в 1977 году и первоначально использовалась в операционной системе 86-DOS. Чтобы добиться переносимости программ из операционной системы CP/M в 86-DOS, в ней были сохранены ранее принятые ограничения на имена файлов. В дальнейшем 86-DOS была приобретена Microsoft и стала основой для ОС MS-DOS 1.0, выпущенной в августе 1981 года. FAT была предназначена для работы с гибкими дисками размером менее 1 Мб и вначале не предусматривала поддержки жёстких дисков.
Структура раздела FAT изображена на рисунке.
Рисунок 1. Структура раздела с файловой системой FAT
В файловой системе FAT дисковое пространство логического раздела делится на две области – системную и область данных (см. рис. 1). Системная область создается и инициализируется при форматировании, а впоследствии обновляется при манипулировании файловой структурой. Системная область файловых систем FAT состоит из следующих компонентов:
- загрузочная запись (boot record, BR);
- резервная область;
- таблицы размещения файлов;
- область корневого каталога (не существует в FAT32).
Область данных логического диска содержит файлы и каталоги, подчиненные корневому, и разделена на участки одинакового размера – кластеры. Кластер может состоять из одного или нескольких последовательно расположенных на диске секторов. Число секторов в кластере должно быть кратно 2N и может принимать значения от 1 до 64. Размер кластера зависит от типа используемой файловой системы и объема логического диска.
Назначение, структура и типы таблицы размещения файлов
Своё название FAT получила от одноимённой таблицы размещения файлов – File Allocation Table, FAT. В таблице размещения файлов хранится информация о кластерах логического диска. Каждому кластеру соответствует элемент таблицы FAT, содержащий информацию о том, свободен данный кластер или занят данными файла. Если кластер занят под файл, то в соответствующем элементе таблицы размещения файлов указывается адрес кластера, содержащего следующую часть файла. Номер начального кластера, занятого файлом, хранится в элементе каталога, содержащего запись об этом файле. Последний элемент списка кластеров содержит признак конца файла (EOF – End Of File). Первые два элемента FAT являются резервными.
Файловая система FAT всегда заполняет свободное место на диске последовательно от начала к концу. При создании нового файла или увеличении уже существующего она ищет самый первый свободный кластер в таблице размещения файлов. Если в процессе работы одни файлы были удалены, а другие изменились в размере, то появляющиеся в результате пустые кластеры будут рассеяны по диску. Если кластеры, содержащие данные файла, расположены не подряд, то файл оказывается фрагментированным.
Существуют следующие типы FAT – FAT12, FAT16, FAT32. Названия типов FAT ведут свое происхождение от размера элемента: элемент FAT12 имеет размер 12 бит (1,5 байт), FAT16 – 16 бит (2 байта), FAT32 – 32 бита (4 байта). В FAT32 четыре старших двоичных разряда зарезервированы и игнорируются в процессе работы операционной системы.
Корневой каталог
За таблицами размещения файлов следует корневой каталог. Каждому файлу и подкаталогу в корневом каталоге соответствует 32-байтный элемент каталога (directory entry), содержащий имя файла, его атрибуты (архивный, скрытый, системный и «только для чтения»), дату и время создания (или внесения в него последних изменений), а также прочую информацию. Для файловых систем FAT12 и FAT16 положение корневого каталога на разделе и его размер жестко зафиксированы. В FAT32 корневой каталог может быть расположен в любом месте области данных раздела и иметь произвольный размер.
Форматы имен файлов
Одной из характеристик ранних версий FAT (FAT12 и FAT16) является использование коротких имен файлов. Короткое имя состоит из двух полей – 8-байтного поля, содержащего собственно имя файла, и 3-байтного поля, содержащего расширение (формат «8.3»). Если введенное пользователем имя файла короче 8 символов, то оно дополняется пробелами (код 0x20); если введенное расширение короче трёх байтов, то оно также дополняется пробелами.
Структура элемента каталога для короткого имени файла представлена в таблице 1.
Первый байт короткого имени выполняет функции признака занятости каталога:
- если первый байт равен 0xE5, то элемент каталога свободен и его можно использовать при создании нового файла;
- если первый байт равен 0x00, то элемент каталога свободен и является началом чистой области каталога (после него нет ни одного задействованного элемента).
Таблица 1. Структура элемента каталога для короткого имени файла
Смещение |
Размер (байт) | Содержание |
0x00 | 11 | Короткое имя файла |
0x0B | 1 | Атрибуты файла |
0x0C | 1 | Зарезервировано для Windows NT. Поле обрабатывается только в FAT32 |
0x0D | 1 | Поле, уточняющее время создания файла (содержит десятки миллисекунд). Поле обрабатывается только в FAT32 |
0x0E | 1 | Время создания файла. Поле обрабатывается только в FAT32 |
0x10 | 2 | Дата создания файла. Поле обрабатывается только в FAT32 |
0x12 | 2 | Дата последнего обращения к файлу для записи или считывания данных. Поле обрабатывается только в FAT32 |
0x14 | 2 | Старшее слово номера первого кластера файла. Поле обрабатывается только в FAT32 |
0x16 | 2 | Время выполнения последней операции записи в файл |
0x18 | 2 | Дата выполнения последней операции записи в файл |
0x1A | 2 | Младшее слово номера первого кластера файла |
0x1C | 4 | Размер файла в байтах |
На использование ASCII-символов в коротком имени накладывается ряд ограничений:
- нельзя использовать символы с кодами меньше 0x20 (за исключением кода 0x05 в первом байте короткого имени);
- нельзя использовать символы с кодами 0x22, 0x2A, 0x2B, 0x2C, 0x2E, 0x2F, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x5B, 0x5C, 0x5D, 0x7C;
- нельзя использовать символ пробела (0x20) в первом байте имени.
В файловых системах FAT32 и VFAT (виртуальная FAT, расширение FAT16) включена поддержка длинных имен файлов (long file name, LFN). Для хранения длинного имени используются элементы каталога, смежные с основным элементом. Имя файла записывается не ASCII-символами, а в Unicode. В одном элементе каталога можно сохранить фрагмент длиной до 13 символов Unicode. Неиспользованный участок последнего фрагмента заполняется кодами 0xFFFF. Структура элемента каталога для длинного имени файла представлена в таблице 2.
Таблица 2. Структура элемента каталога для длинного имени файла
Смещение | Размер (байт) | Содержание |
0x00 | 1 | Номер фрагмента |
0x01 | 10 | Символы 1-5 имени файла в Unicode |
0x0B | 1 | Атрибуты файла |
0x0C | 1 | Байт флагов |
0x0D | 1 | Контрольная сумма короткого имени |
0x0E | 12 | Символы 6-11 имени файла в Unicode |
0x1A | 2 | Номер первого кластера (заполняется нулями) |
0x1C | 4 | Символы 12-13 имени файла в Unicode |
Длинное имя записывается в каталог первым, причем фрагменты размещены в обратном порядке, начиная с последнего. Вслед за длинным (полным) именем размещается стандартный описатель файла, содержащий укороченный по специальному алгоритму вариант этого имени. Пример хранения длинного имени файла показан здесь: http://www.ntfs.com/fat-filenames.htm.
Загрузочный сектор
В первом секторе логического диска с системой FAT располагается загрузочный сектор и блок параметров BIOS. Начальный участок данного блока для всех типов FAT идентичен (таблица 3). Различия в структуре загрузочных секторов для разных типов FAT начинаются со смещения 0x24. Для FAT12 и FAT16 структура имеет вид, показанный в таблице 4, для FAT32 – в таблице 5.
Таблица 3. Начальный участок загрузочного сектора
Смещение | Размер, байт | Описание |
0x00 | 3 | Безусловный переход (jmp) на загрузочный код |
0x03 | 8 | Идентификатор фирмы-изготовителя |
0x0B | 2 | Число байт в секторе (512) |
0x0D | 1 | Число секторов в кластере |
0x0E | 2 | Число резервных секторов в резервной области раздела, начиная с первого сектора раздела |
0x10 | 1 | Число таблиц (копий) FAT |
0x11 | 2 | Для FAT12/FAT16 — количество 32-байтных дескрипторов файлов в корневом каталоге; для FAT32 это поле имеет значение 0 |
0x13 | 2 | Общее число секторов в разделе; если данное поле содержит 0, то число секторов задается полем по смещению 0x20 |
0x15 | 1 | Тип носителя. Для жесткого диска имеет значение 0xF8; для гибкого диска (2 стороны, 18 секторов на дорожке) – 0xF0 |
0x16 | 2 | Для FAT12/FAT16 это поле содержит количество секторов, занимаемых одной копией FAT; для FAT32 это поле имеет значение 0 |
0x18 | 2 | Число секторов на дорожке (для прерывания 0x13) |
0x1A | 2 | Число рабочих поверхностей (для прерывания 0x13) |
0x1C | 4 | Число скрытых секторов перед разделом |
0x20 | 4 | Общее число секторов в разделе. Поле используется, если в разделе свыше 65535 секторов, в противном случае поле содержит 0. |
Таблица 4. Структура загрузочного сектора FAT12/FAT16
Смещение Размер, байт Описание 0x24 1 Номер дисковода для прерывания 0х13 0x25 10x26 1 Признак расширенной загрузочной записи (0x29) 0x27 4 Номер логического диска 0x2B 11 Метка диска 0x36 8 Текстовая строка с аббревиатурой типа файловой системы
Зарезервировано для Windows NT, имеет значение 0
Таблица 5. Структура загрузочного сектора FAT32
Размер, байт Описание 4 Количество секторов, занимаемых одной копией FAT 2 Номер активной FAT 2 Номер версии FAT32: старший байт — номер версии,младший – номер ревизии. В настоящее время используется значение 0:0 4 Номер кластера для первого кластера корневого каталога 2 Номер сектора структуры FSINFO в резервной области логического диска 2 Номер сектора(в резервной области логического диска), используемогодля хранения резервной копии загрузочного сектора 12 Зарезервировано (содержит 0)
Смещение |
0x24 |
0x28 |
0x2A |
0x2С |
0x30 |
0x32 |
0x34 |
Кроме перечисленных в таблицах 2-го и 3-го полей, нулевой сектор логического диска должен содержать в байте со смещением 0x1FE код 0x55, а в следующем байте (смещение 0x1FF) – код 0xAA. Указанные два байта являются признаком загрузочного диска.
Таким образом, загрузочный сектор выполняет две важные функции: описывает структуру данных на диске, а также позволяет осуществить загрузку операционной системы.
На логическом диске с организацией FAT32 дополнительно присутствует структура FSInfo, размещаемая в первом секторе резервной области. Эта структура содержит информацию о количестве свободных кластеров на диске и о номере первого свободного кластера в таблице FAT. Формат структуры описан в таблице 6.
Таблица 6. Структура сектора FSInfo и резервного загрузочного сектора FAT32
Размер, байт Описание 4 Значение 0x41615252 – сигнатура, которая служит признаком того, данный сектор содержит структуру FSInfo 480 Зарезервировано (содержит 0) 4 Значение 0x61417272 (сигнатура) 4 Содержит текущее число свободных кластеров на диске. Если в поле записано значение 0xFFFFFFFF, то число свободных кластеров неизвестно, и его необходимо вычислять 4 Содержит номер кластера, с которого дисковый драйвер должен начинать поиск свободных кластеров. Если в поле записано значение 0xFFFFFFFF, то поиск свободных кластеров нужно начинать с кластера номер 2 12 Зарезервировано (содержит 0) 4 Сигнатура 0xAA550000 – признак конца структуры FSInfo
Смещение |
0x000 |
0x004 |
0x1E4 |
0x1E8 |
0x1EC |
0x1F0 |
0x1FC |
Для доступа к содержимому файла, находящемуся на разделе с файловой системой FAT, необходимо получить номер первого кластера файла. Этот номер, как мы уже установили, входит в состав элемента каталога, содержащего запись о файле. Номеру первого кластера соответствует элемент таблицы FAT, в котором хранится адрес кластера, содержащего следующую часть файла. Элемент FAT, соответствующий последнему кластеру в цепочке, содержит сигнатуру конца файла. Для FAT12 это значение составляет 0xFFF, для FAT16 – 0xFFFF, для FAT32 – 0xFFFFFFFF.
Рассмотрим программную реализацию алгоритма чтения для каждого типа FAT, и начнём с FAT16.
Все исходные тексты, рассматриваемые в статье, доступны на сайте журнала.
Программная реализация алгоритма чтения файла с логического раздела с файловой системой FAT16
Разработаем модуль, выполняющий чтение N первых кластеров файла, созданного на разделе с файловой системой FAT16. Параметр N (число кластеров для считывания) является переменной величиной и задается пользователем. Имя файла соответствует формату «8.3», т.е. является коротким. Модуль функционирует под управлением ОС Linux.
Определим необходимые заголовочные файлы:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/msdos_fs.h>
#include «split.h»
Заголовочный файл split.h имеет следующее содержание:
#include <linux/types.h>
#define SHORT_NAME 13 // максимальная длина короткого имени файла
struct split_name {
__u8 name[9]; // имя файла
__u8 ext[4]; // расширение файла
int name_len, // длина имени файла
ext_len; // длина расширения файла
};
Cтруктура split_name предназначена для хранения составных частей короткого имени файла (имени и расширения) и их длин.
В заголовочном файле определены структурные типы, описывающие основные компоненты файловой системы FAT – загрузочный сектор, сектор FSInfo, структуры элементов каталога для короткого и длинного имён файлов.
Рассмотрим кратко поля, которые входят в каждую из этих структур.
- Структура загрузочного сектора struct fat_boot_sector:
- __s8 system_id[8] – системный идентификатор;
- __u8 sector_size[2] – размер сектора в байтах;
- __u8 cluster_size – размер кластера в секторах;
- __u16 reserved – число резервных секторов в резервной области раздела;
- __u8 fats – количество копий FAT;
- __u8 dir_entries[2] – количество 32-байтных дескрипторов файлов в корневом каталоге;
- __u8 sectors[2] – число секторов на разделе; если это поле равно 0, используется поле total_sect;
- __u8 media – тип носителя, на котором создана файловая система;
- __u16 fat_length – размер FAT в секторах;
- __u32 total_sect – размер раздела FAT в секторах (если поле sectors == 0).
- __u32 fat32_length – размер FAT32 в секторах;
- __u32 root_cluster – номер первого кластера корневого каталога;
- __u16 info_sector – номер сектора, содержащего структуру FSInfo.
Следующие поля данной структуры используются только FAT32:
- Структура сектора FSInfo struct fat_boot_fsinfo:
- __u32 signature1 – сигнатура 0x41615252;
- __u32 signature2 – сигнатура 0x61417272;
- __u32 free_clusters – количество свободных кластеров. Если поле содержит -1, поиск свободных кластеров нужно начинать с кластера номер 2.
- Структура элемента каталога короткого имени struct msdos_dir_entry:
- __s8 name[8],ext[3] – имя и расширение файла;
- __u8 attr – атрибуты файла;
- __u8 ctime_ms – это поле уточняет время создания файла до мс (используется только FAT32);
- __u16 ctime – время создания файла (используется только FAT32);
- __u16 cdate – дата создания файла (используется только FAT32);
- __u16 adate – дата последнего доступа к файлу (используется только FAT32);
- __u16 starthi – старшие 16 бит номера первого кластера файла (используется только FAT32);
- __u16 time,date,start – время и дата создания файла, номер первого кластер файла;
- __u32 size – размер файла (в байтах).
- Структура элемента каталога длинного имени:
- __u8 id – номер элемента;
- __u8 name0_4[10] – символы 1 – 5 имени;
- __u8 attr – атрибуты файла;
- __u8 alias_checksum – контрольная сумма короткого имени;
- __u8 name5_10[12] – символы 6 – 11 имени;
- __u8 name11_12[4] – символы 12 – 13 имени.
Продолжим рассмотрение программной реализации алгоритма и определим имя раздела, на котором создана файловая система FAT16:
#ifndef FAT16_PART_NAME
#define FAT16_PART_NAME «/dev/hda1»
#endif
Глобальные структуры:
struct fat_boot_sector fbs; // структура загрузочного сектора
struct msdos_dir_entry dentry; // структура элемента каталога
Глобальные переменные:
__u16 *fat16; // сюда копируем таблицу FAT16
__u16 sector_size; // размер сектора (из FAT16)
__u16 dir_entries; // число 32-байтных дескрипторов
// в root-каталоге (0 для FAT32)
__u16 sectors; // общее число секторов в разделе
__u32 fat16_size; // размер FAT16
__u32 root_size; // размер корневого каталога
__u32 data_start; // начало области данных
__u16 byte_per_cluster; // размер кластера в байтах
__u16 next_cluster; // очередной кластер в цепочке
__u8 *dir_entry = NULL; // указатель на записи каталога
int hard; // дескриптор файла устройства
int fat;
Начнём рассмотрение с главной функции:
int main()
{
int num;
Задаем полное имя файла, содержимое которого мы хотим прочитать. Напомню, что мы работаем только с короткими именами файлов. Порядок работы с длинными именами в данной статье не рассматривается.
__u8 *full_path = «/Folder1/Folder2/text.txt»;
Открываем файл устройства:
hard = open(FAT16_PART_NAME, O_RDONLY);
if(hard < 0) {
perror(FAT16_PART_NAME);
exit(-1);
}
Считываем первые 10 кластеров файла. Считывание выполняет функция fat16_read_file(). Параметры функции – полное имя файла и число кластеров для чтения. Функция возвращает число прочитанных кластеров или -1, если при чтении произошла ошибка:
num = fat16_read_file(full_path, 10);
if(num < 0) perror(«fat16_read_file»);
else printf(«Read %d clusters «, num);
Закрываем файл устройства и выходим:
close(hard);
return 0;
}
Функция чтения кластеров файла имеет следующий вид:
int fat16_read_file(__u8 *full_path, int num)
{
struct split_name sn; // структура для хранения составных частей файла
__u8 tmp_name_buff[SHORT_NAME]; // буфер для временного хранения составных элементов полного пути файла
static int i = 1;
int n;
__u8 *tmp_buff;
__u16 start_cluster, next_cluster;
Параметры функции мы перечислили при рассмотрении функции main.
Подготовительные операции – обнуляем буфер tmp_name_buff и структуру struct split_name sn:
memset(tmp_name_buff, 0, SHORT_NAME);
memset((void *)&sn, 0, sizeof(struct split_name));
Первым символом в абсолютном путевом имени файла должен быть прямой слэш (/). Проверяем это:
if(full_path[0] != «/») return -1;
Считываем с раздела загрузочный сектор:
if(read_fbs() < 0) return -1;
Считанный загрузочный сектор находится сейчас в глобальной структуре struct fat_boot_sector fbs. Скопируем из этой структуры размер сектора, число записей в корневом каталоге и общее число секторов на разделе:
memcpy((void *)§or_size, (void *)fbs.sector_size, 2);
memcpy((void *)&dir_entries, (void *)fbs.dir_entries, 2);
memcpy((void *)§ors, (void *)fbs.sectors, 2);
Определим размер кластера в байтах:
byte_per_cluster = fbs.cluster_size * 512
Отобразим информацию, находящуюся в загрузочном секторе:
printf(«System id — %s «, fbs.system_id);
printf(«Sector size — %d «, sector_size);
printf(«Cluster size — %d «, fbs.cluster_size);
printf(«Reserved — %d «, fbs.reserved);
printf(«FATs number — %d «,fbs.fats);
printf(«Dir entries — %d «, dir_entries);
printf(«Sectors — %d «, sectors);
printf(«Media — 0x%X «, fbs.media);
printf(«FAT16 length — %u «, fbs.fat_length);
printf(«Total sect — %u «, fbs.total_sect);
printf(«Byte per cluster — %d «, byte_per_cluster);
Вычисляем размер FAT16 в байтах и считываем её:
fat16_size = fbs.fat_length * 512;
if(read_fat16() < 0) return -1;
Считываем корневой каталог:
if(read_root_dentry() < 0) return -1;
Сейчас указатель dir_entry позиционирован на область памяти, содержащую записи корневого каталога. Размер этой области памяти равен размеру корневого каталога (root_size).
Сохраним (для контроля) содержимое корневого каталога в отдельном файле:
#ifdef DEBUG
fat = open(«dir16», O_CREAT|O_WRONLY, 0600);
write(fat, dir_entry, root_size);
close(fat);
#endif
Вычисляем начало области данных:
data_start = 512 * fbs.reserved + fat16_size * fbs.fats + root_size;
Имея все записи корневого каталога, мы можем добраться до содержимого файла test.txt. С этой целью организуем цикл. В теле цикла проведем разбор полного имени файла, выделяя его элементы – подкаталоги (их у нас два, Folder1 и Folder2) и имя искомого файла (test.txt).
while(1) {
memset(tmp_name_buff, 0, SHORT_NAME);
memset((void *)&sn, 0, sizeof(struct split_name));
for(n = 0 ; n < SHORT_NAME; n++, i++) {
tmp_name_buff[n] = full_path[i];
if((tmp_name_buff[n] == «/») || (tmp_name_buff[n] == «?»)) {
i++;
break;
}
}
tmp_name_buff[n] = «?»;
Заполняем структуру struct split_name sn соответствующей информацией. Заполнение выполняет функция split_name, при этом выполняется проверка имени файла на соответствие формату «8.3»:
if(split_name(tmp_name_buff, &sn) < 0) {
printf(«not valid name «);
return -1;
}
Для каждого элемента полного имени файла определяем начальный кластер. Для этого ищем в элементах каталога (начиная с корневого) запись, соответствующую элементу полного имени, и считываем эту запись. Процедуру поиска выполняет функция get_dentry():
if(get_dentry(&sn) < 0) {
printf(«No such file! «);
return -1;
}
Проверяем атрибуты файла. Если это каталог, считываем его содержимое и продолжаем цикл:
if(dentry.attr & 0x10) {
if(read_directory(dentry.start) < 0) return -1;
continue;
}
Если это файл – считываем первые num кластеров. Для контроля считанную информацию сохраним в отдельном файле:
if(dentry.attr & 0x20) {
start_cluster = dentry.start;
tmp_buff = (__u8 *)malloc(byte_per_cluster); // сюда будет считываться содержимое кластера
n = open(«clust», O_CREAT|O_RDWR, 0600); // в этом файле сохраним считанную информацию
if(n < 0) {
perror(«open»);
return -1;
}
printf(«file`s first cluster — 0x%X .. «, start_cluster);
Для считывания кластеров файла организуем цикл:
for(i = 0; i < num; i++) {
memset(tmp_buff, 0, byte_per_cluster);
Считываем содержимое кластера в буфер tmp_buff и сохраняем его в отдельном файле:
if(read_cluster(start_cluster, tmp_buff) < 0) return -1;
if(write(n, tmp_buff, byte_per_cluster) < 0) {
perror(«write»);
close(n);
return -1;
}
Считываем из FAT16 номер следующего кластера, занятого под данный файл. Если это последний кластер – прерываем цикл и возвращаемся в главную функцию:
next_cluster = fat16[start_cluster];
#ifdef DEBUG
printf(«OK. Readed «);
printf(«file`s next cluster — 0x%X .. «, next_cluster);
#endif
if(next_cluster == EOF_FAT16) {
#ifdef DEBUG
printf(«last cluster. «);
#endif
free(tmp_buff);
close(n);
return ++i;
}
start_cluster = next_cluster;
}
#ifdef DEBUG
printf(«stop reading «);
#endif
return i;
}
}
}
Чтение загрузочного сектора FAT16 выполняет функция read_fbs(). Результат помещается в глобальную структуру fbs:
int read_fbs()
{
if(read(hard,(__u8 *)&fbs, sizeof(fbs)) < 0) return -1;
return 0;
}
Чтение таблицы размещения файлов файловой системы FAT16 выполняет функция read_fat16():
int read_fat16()
{
__u64 seek = (__u64)(fbs.reserved) * 512; // смещение к FAT16 от начала раздела
fat16 = (void *)malloc(fat16_size);
if(pread64(hard, (__u8 *)fat16, fat16_size, seek) < 0) return -1;
return 0;
}
Чтение корневого каталога выполняет функция read_root_dentry():
int read_root_dentry()
{
__u64 seek = (__u64)fbs.reserved * 512 + fat16_size * fbs.fats; // смещение к корневому каталогу от начала раздела
root_size = 32 * dir_entries; // вычисляем размер корневого каталога
dir_entry = (__u8 *)malloc(root_size);
if(!dir_entry) return -1;
memset(dir_entry, 0, root_size);
if(pread64(hard, dir_entry, root_size, seek) < 0) return -1;
return 0;
}
Чтение кластера, принадлежащего файлу, выполняет функция read_cluster(). Входные параметры функции – номер кластера cluster_num и указатель на буфер __u8 *tmp_buff, куда нужно поместить результат чтения. Смещение к кластеру на разделе вычисляется по формуле (см. [1]):
SEEK = DATA_START + (CLUSTER_NUM — 2) * BYTE_PER_CLUSTER,
где:
- SEEK – смещение к кластеру на разделе
- DATA_START – начало области данных
- CLUSTER_NUM – порядковый номер кластера
- BYTE_PER_CLUSTER – размер кластера в байтах
int read_cluster(__u16 cluster_num, __u8 *tmp_buff)
{
__u64 seek = (__u64)(byte_per_cluster) * (cluster_num — 2) + data_start; // вычисляем смещение к кластеру
if(pread64(hard, tmp_buff, byte_per_cluster, seek) < 0) return -1;
return 0;
}
Функция read_directory выполняет чтение записей каталога (не корневого) и помещает результат в область памяти, на которую настроен указатель dir_entry:
int read_directory(__u16 start_cluster)
{
int i = 1;
__u16 next_cluster;
for(; ;i++) {
Выделяем память для хранения содержимого каталога, считываем содержимое стартового кластера и получаем из таблицы FAT16 значение очередного кластера:
dir_entry = (__u8 *)realloc(dir_entry, i * byte_per_cluster);
if(!dir_entry) return -1;
if(read_cluster(start_cluster, (dir_entry + (i — 1) * byte_per_cluster)) < 0) return -1;
next_cluster = fat16[start_cluster];
Сохраним содержимое каталога в отдельном файле (для контроля):
#ifdef DEBUG
printf(«Next cluster — 0x%X «, next_cluster);
fat = open(«dir16», O_CREAT|O_WRONLY, 0600);
write(fat, dir_entry, root_size);
close(fat);
#endif
Если достигнут последний кластер, выходим из цикла, иначе продолжаем чтение каталога, увеличив размер буфера dir_entry ещё на один кластер:
if(next_cluster & EOF_FAT16) break;
start_cluster = next_cluster;
}
return 0;
}
Поиск в содержимом каталога элемента, соответствующего искомому файлу, выполняет функция get_dentry(). Входные параметры этой функции – указатель на структуру struct split_name *sn, содержащую элементы короткого имени файла:
int get_dentry(struct split_name *sn)
{
int i = 0;
В глобальном буфере dir_entry находится массив элементов каталога, в котором мы собираемся искать запись файла (или каталога). Для поиска организуем цикл. В теле цикла производим копирование элементов каталога в глобальную структуру dentry и сравниваем значение полей name и ext этой структуры с соответствующими полями структуры struct split_name *sn. Совпадение этих полей означает, что мы нашли в массиве элементов каталога запись искомого файла:
for(; ; i++) {
memcpy((void *)&dentry, dir_entry + i * sizeof(dentry), sizeof(dentry));
if(!(memcmp(dentry.name, sn->name, sn->name_len)) &&
!(memcmp(dentry.ext, sn->ext, sn->ext_len)))
break;
if(!dentry.name[0]) return -1;
}
#ifdef DEBUG
printf(«name — %s «, dentry.name);
printf(«start cluster — 0x%X «, dentry.start);
printf(«file size — %u «, dentry.size);
printf(«file attrib — 0x%X «, dentry.attr);
#endif
return 0;
}
Весь вышеприведенный код находится в каталоге FAT16, файл fat16.c. Для получения исполняемого модуля создадим Makefile следующего содержания:
INCDIR = /usr/src/linux/include
.PHONY = clean
fat16: fat16.o split.o
gcc -I$(INCDIR) $^ -g -o $@
%.o: %.c
gcc -I$(INCDIR) -DDEBUG -c $^
clean:
rm -f *.o
rm -f ./fat16
Программная реализация алгоритма чтения файла с логического раздела с файловой системой FAT12
В целом алгоритм чтения файла с раздела FAT12 идентичен алгоритму чтения файла с раздела FAT16. Отличие заключается в процедуре чтения элементов из таблицы FAT12. Таблица FAT16 рассматривалась нами как простой массив 16-разрядных элементов. Для чтения элементов таблицы FAT12 в [1] предложен следующий алгоритм:
- умножить номер элемента на 1.5;
- извлечь из FAT 16-разрядное слово, используя в качестве смещения результат предыдущей операции;
- если номер элемента четный, выполнить операцию AND над считанным словом и маской 0x0FFF. Если номер нечетный, сдвинуть считанное из таблицы слово на 4 бита в сторону младших разрядов.
Базируясь на этом алгоритме, реализуем функцию чтения элементов из таблицы FAT12:
int get_cluster(__u16 cluster_num)
{
__u16 seek;
__u16 clust;
Вычисляем смещение в таблице FAT12 и считываем из таблицы 16-разрядное слово:
seek = (cluster_num * 3) / 2;
memcpy((__u8 *)&clust, (__u8 *)(fat12 + seek), 2);
Если стартовый номер кластера – четное число, сдвигаем считанное из таблицы значение на 4 бита в сторону младших разрядов, если нечетное – суммируем его с 0x0FFF:
if(cluster_num % 2) clust >>= 4;
else clust &= 0x0FFF;
Этот фрагмент можно также реализовать на ассемблере:
asm(
» xorw %%ax, %%ax «
» btw $0, %%cx «
» jnc 1f «
» shrw $4, %%dx «
» jmp 2f «
«1: andw $0x0FFF, %%dx «
«2: movw %%dx, %%ax «
:»=a» (next)
:»d» (clust), «c» (cluster_num));
Возвращаем результат:
return clust;
}
Остановимся чуть подробнее на самом алгоритме. Предположим, что на разделе с FAT12 создан файл, который занимает 9-й и 10-й кластеры. Каждый элемент FAT12 занимает 12 бит. Т.к. из таблицы мы считываем 16-разрядные элементы, то смещение к 9-му элементу будет равно 13 байт (9 * 1.5 = 13, остаток отбрасываем), при этом младшие 4 разряда будут принадлежать 8-му элементу FAT. Их необходимо отбросить, а для этого достаточно сдвинуть считанный элемент на 4 бита в сторону младших разрядов, что и предусмотрено алгоритмом. Смещение к 10-му элементу будет равно 15 байт, и старшие 4 бита будут принадлежать 11-му элементу FAT. Чтобы их отбросить, необходимо выполнить операцию AND над 10-м элементом и маской 0x0FFF, что так же соответствует вышеприведенному алгоритму.
Исходные тексты модуля чтения файла с раздела FAT12 находятся в каталоге FAT12, файл fat12.c.
Программная реализация алгоритма чтения файла с логического раздела с файловой системой FAT32
Алгоритм чтения файла с раздела с файловой системой FAT32 практически не отличается от алгоритма для FAT16, за исключением того, что в FAT32 корневой каталог может располагаться в любом месте раздела и иметь произвольный размер. Поэтому, чтобы было интереснее, усложним задачу – предположим, что нам известен только номер раздела с файловой системой FAT32. Чтобы считать с этого раздела информацию, необходимо вначале определить его координаты – смещение к разделу от начала диска. А для этого надо иметь представление о логической структуре жесткого диска.
Логическая структура жесткого диска
Рассмотрим логическую структуру жесткого диска, соответствующую стандарту Microsoft – «основной раздел – расширенный раздел – разделы non-DOS».
Пространство на жестком диске может быть организовано в виде одного или нескольких разделов, а разделы могут содержать один или несколько логических дисков.
На жестком диске по физическому адресу 0-0-1 располагается главная загрузочная запись (Master Boot Record, MBR). В структуре MBR находятся следующие элементы:
- внесистемный загрузчик (non-system bootstrap – NSB);
- таблица описания разделов диска (таблица разделов, partition table, PT). Располагается в MBR по смещению 0x1BE и занимает 64 байта;
- сигнатура MBR. Последние два байта MBR должны содержать число 0xAA55.
Таблица разделов описывает размещение и характеристики имеющихся на винчестере разделов. Разделы диска могут быть двух типов – primary (первичный, основной) и extended (расширенный). Максимальное число primary-разделов равно четырем. Наличие на диске хотя бы одного primary-раздела является обязательным. Extended-раздел может быть разделен на большое количество подразделов – логических дисков. Упрощенно структура MBR представлена в таблице 7. Таблица разделов располагается в конце MBR, для описания раздела в таблице отводится 16 байт.
Таблица 7. Структура MBR
Смещение Размер, байт0 4460x1BE 160x1CE 160x1DE 160x1EE 160x1FE 2
Содержимое (contents) |
Программа анализа таблицы разделов и загрузки с активного раздела |
Partition 1 entry (элемент таблицы разделов) |
Partition 2 entry |
Partition 3 entry |
Partition 4 entry |
Сигнатура 0xAA55 |
Структура записи элемента таблицы разделов показана в таблице 8.
Таблица 8. Структура записи элемента таблицы разделов
Смещение | Размер, байт | Содержание |
0x00 | 1 | Признак активности (0 — раздел не активный, 0x80 – раздел активный) |
0x01 | 1 | Номер головки диска, с которой начинается раздел |
0x02 | 2 | Номер цилиндра и номер сектора, с которых начинается раздел |
0x04 | 1 | Код типа раздела System ID |
0x05 | 1 | Номер головки диска, на которой заканчивается раздел |
0x06 | 2 | Номер цилиндра и номер сектора, которыми заканчивается раздел |
0x08 | 4 | Абсолютный (логический) номер начального сектора раздела |
0x0C | 4 | Размер раздела (число секторов) |
Первым байтом в элементе раздела идет флаг активности раздела (0 – неактивен, 0x80 – активен). Он служит для определения, является ли раздел системным загрузочным и есть ли необходимость производить загрузку операционной системы с него при старте компьютера. Активным может быть только один раздел. За флагом активности раздела следуют координаты начала раздела – три байта, означающие номер головки, номер сектора и номер цилиндра. Номера цилиндра и сектора задаются в формате прерывания Int 0x13, т.е. биты 0-5 содержат номер сектора, биты 6-7 – старшие два бита 10-разрядного номера цилиндра, биты 8-15 – младшие восемь бит номера цилиндра. Затем следует кодовый идентификатор System ID, указывающий на принадлежность данного раздела к той или иной операционной системе. Идентификатор занимает один байт. За системным идентификатором расположены координаты конца раздела – три байта, содержащие номера головки, сектора и цилиндра соответственно. Следующие четыре байта – это число секторов перед разделом, и последние четыре байта – размер раздела в секторах.
Таким образом, элемент таблицы раздела можно описать при помощи следующей структуры:
struct pt_struct {
u8 bootable; // флаг активности раздела
u8 start_part[3]; // координаты начала раздела
u8 type_part; // системный идентификатор
u8 end_part[3]; // координаты конца раздела
u32 sect_before; // число секторов перед разделом
u32 sect_total; // размер раздела в секторах (число секторов в разделе)
};
Элемент первичного раздела указывает сразу на загрузочный сектор логического диска (в первичном разделе всегда имеется только один логический диск), а элемент расширенного раздела – на список логических дисков, составленный из структур, которые именуются вторичными MBR (Secondary MBR, SMBR).
Свой блок SMBR имеется у каждого диска расширенного раздела. SMBR имеет структуру, аналогичную MBR, но загрузочная запись у него отсутствует (заполнена нулями), а из четырех полей описателей разделов используются только два. Первый элемент раздела при этом указывает на логический диск, второй элемент указывает на следующую структуру SMBR в списке. Последний SMBR списка содержит во втором элементе нулевой код раздела.
Вернемся к рассмотрению модуля чтения файла с раздела FAT32.
Заголовочные файлы:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/msdos_fs.h>
Сигнатура MBR:
#define SIGNATURE 0xAA55
Файл устройства, с которого будет считываться информация о разделах:
#define DEVICE «/dev/hda»
Размер элемента таблицы разделов (16 байт):
#define PT_SIZE 0x10
Следующий массив структур устанавливает соответствие между кодом типа раздела и его символьным отображением:
struct systypes {
__u8 part_type;
__u8 *part_name;
};
struct systypes i386_sys_types[] = {
{0x00, «Empty»},
{0x01, «FAT12»},
{0x04, «FAT16 <32M»},
{0x05, «Extended»},
{0x06, «FAT16»},
{0x0b, «Win95 FAT32»},
{0x0c, «Win95 FAT32 (LBA)»},
{0x0e, «Win95 FAT16 (LBA)»},
{0x0f, «Win95 Ext»d (LBA)»},
{0x82, «Linux swap»},
{0x83, «Linux»},
{0x85, «Linux extended»},
{0x07, «HPFS/NTFS»}
};
Определим число элементов в массиве i386_sys_types при помощи макроса PART_NUM:
#define PART_NUM (sizeof(i386_sys_types) / sizeof(i386_sys_types[0]))
Установим ограничение на количество логических дисков:
#define MAX_PART 20
Следующий массив структуры будет содержать информацию о логических дисках на устройстве (жестком диске):
struct pt_struct {
__u8 bootable;
__u8 start_part[3];
__u8 type_part;
__u8 end_part[3];
__u32 sect_before;
__u32 sect_total;
} pt_t[MAX_PART];
int hard; // дескриптор файла устройства
__u8 mbr[512]; // сюда считаем MBR
Номер раздела, на котором создана файловая система FAT32:
#define FAT32_PART_NUM 5
Структуры загрузочного сектора, сектора FSInfo и элемента каталога (определены в файле <linux/msdos>):
struct fat_boot_sector fbs;
struct fat_boot_fsinfo fsinfo;
struct msdos_dir_entry dentry;
__u32 *fat32 = NULL; // сюда копируем таблицу FAT32
__u16 sector_size; // размер сектора (из FAT32)
__u16 dir_entries; // 0 для FAT32
__u16 sectors; // число секторов на разделе
__u32 fat32_size; // размер FAT32
__u32 data_start; // начало области данных
__u16 byte_per_cluster; // сколько байт в кластере (размер кластера в байтах)
__u32 next_cluster; // очередной кластер в цепочке
__u32 root_cluster; // ROOT cluster — начальный кластер корневого каталога
__u8 *dir_entry = NULL; // указатель на записи каталога
__u64 start_seek = 0; // стартовое смещение к разделу (в байтах)
Главная функция:
int main()
{
int num = 0;
int cluster_num = 5; // сколько кластеров считывать из файла
__u8 *full_path = «/Folder1/Folder2/readme»; // файл для считывания
Открываем устройство, получаем информацию о таблице разделов на устройстве и отображаем информацию о разделах:
hard = open(DEV_NAME, O_RDONLY);
if(hard < 0) {
perror(DEV_NAME);
exit(-1);
}
if(get_pt_info(hard) < 0) {
perror(«get_pt_info»);
exit(-1);
}
show_pt_info();
Вычисляем стартовое смещение к разделу:
start_seek = (__u64)(pt_t[FAT32_PART_NUM — 1].sect_before) * 512;
Считываем кластеры, принадлежащие файлу:
num = fat32_read_file(full_path, cluster_num);
if(num < 0) perror(«fat32_read_file»);
else printf(«Read %d clusters\n», num);
close(hard);
return 0;
}
Информацию о таблице разделов считывает функция get_pt_info():
int get_pt_info(int hard)
{
int i = 0;
__u64 seek;
Считываем таблицу разделов из MBR и проверяем сигнатуру:
read_main_ptable(hard);
if(check_sign() < 0) {
printf(«Not valid signature!\n»);
return -1;
}
Ищем идентификатор расширенного раздела. Если таковой имеется, вычисляем смещение к расширенному разделу и считываем информацию о логических дисках:
for(; i < 4; i++) {
if((pt_t[i].type_part == 0xF) || \
(pt_t[i].type_part == 0x5) || \
(pt_t[i].type_part == 0x0C)) {
seek = (__u64)pt_t[i].sect_before * 512;
read_ext_ptable(hard, seek);
break;
}
}
return 0;
}
Функция чтения таблицы разделов read_main_ptable():
void read_main_ptable(int hard)
{
if(read(hard, mbr, 512) < 0) {
perror(«read»);
close(hard);
exit(-1);
}
memset((void *)pt_t, 0, (PT_SIZE * 4));
memcpy((void *)pt_t, mbr + 0x1BE, (PT_SIZE * 4));
return;
}
Функция проверки сигнатуры check_sign():
int check_sign()
{
__u16 sign = 0;
memcpy((void *)&sign, (void *)(mbr + 0x1FE), 2);
#ifdef DEBUG
printf(«Signature — 0x%X\n», sign);
#endif
if(sign != SIGNATURE) return -1;
return 0;
}
Функция чтения расширенной таблицы разделов:
void read_ext_ptable(int hard, __u64 seek)
{
int num = 4; // начиная с этой позиции, массив структур pt_t будет заполняться информацией о логических дисках
__u8 smbr[512];
Входные данные:
- hard – дескриптор файла устройства;
- seek – смещение к расширенному разделу от начала диска (в байтах).
Для получения информации о логических дисках организуем цикл:
for(;;num++) {
Считываем SMBR, находящуюся по смещению seek от начала диска:
memset((void *)smbr, 0, 512);
pread64(hard, smbr, 512, seek);
Заполняем два элемента таблицы pt_t, начиная с позиции num. Первый элемент будет указывать на логический диск, а второй – на следующую структуру SMBR:
memset((void *)&pt_t[num], 0, PT_SIZE * 2);
memcpy((void *)&pt_t[num], smbr + 0x1BE, PT_SIZE * 2);
Вносим поправку в поле «Номер начального сектора» – отсчет ведется от начала диска:
pt_t[num].sect_before += (seek / 512);
Если код типа раздела равен нулю, то больше логических дисков нет:
if(!(pt_t[num + 1].type_part)) break;
Вычисляем смещение к следующему SMBR:
seek = ((__u64)(pt_t[num].sect_before + pt_t[num].sect_total)) * 512;
}
return;
}
Функция show_pt_info() отображает информацию о найденных логических дисках на устройстве:
void show_pt_info()
{
int i = 0, n;
#ifdef DEBUG
printf(«Число разделов на диске — %d\n», PART_NUM);
#endif
for(; i < MAX_PART; i++) {
if(!pt_t[i].type_part) break;
printf(«\nТип раздела %d — «, i);
for(n = 0; n < PART_NUM; n++) {
if(pt_t[i].type_part == i386_sys_types[n].part_type) {
printf(«%s\n», i386_sys_types[n].part_name);
break;
}
}
if(n == PART_NUM) printf(«unknown type\n»);
printf(«Признак загрузки — 0x%X\n», pt_t[i].bootable);
printf(«Секторов в разделе %d — %d\n», i, pt_t[i].sect_total);
printf(«Секторов перед разделом %d — %d\n\n», i, pt_t[i].sect_before);
}
return;
}
Чтение кластеров файла с раздела FAT32 выполняет функция fat32_read_file(). Эта функция имеет много общего с функцией fat16_read_file(), поэтому за подробными комментариями обратитесь к п. 6:
int fat32_read_file(__u8 *full_path, int num)
{
struct split_name sn;
__u8 tmp_name_buff[SHORT_NAME];
int i = 1, n;
__u32 start_cluster, next_cluster;
__u8 *tmp_buff;
Подготовительные операции – чистим буфер, структуру и проверяем первый слэш:
memset(tmp_name_buff, 0, SHORT_NAME);
memset((void *)&sn, 0, sizeof(struct split_name));
if(full_path[0] != ‘/’) return -1;
Считываем загрузочный сектор:
if(read_fbs() < 0) return -1;
memcpy((void *)§or_size, (void *)fbs.sector_size, 2);
memcpy((void *)&dir_entries, (void *)fbs.dir_entries, 2);
memcpy((void *)§ors, (void *)fbs.sectors, 2);
Считываем структуру FSInfo и отобразим сигнатуру, находящуюся в ней:
if(read_fs_info() < 0) return -1;
printf(«Signature1 — 0x%X\n», fsinfo.signature1);
printf(«Signature2 — 0x%X\n», fsinfo.signature2);
fat32_size = fbs.fat32_length * 512; // размер FAT32 в байтах
data_start = 512 * fbs.reserved + fat32_size * 2; // начало поля данных
byte_per_cluster = fbs.cluster_size * 512; // размер кластера в байтах
root_cluster = fbs.root_cluster; // номер кластера корневого каталога
Считываем FAT32:
if(read_fat32() < 0) return -1;
Выделяем память для записей каталога:
dir_entry = (__u8 *)malloc(byte_per_cluster);
if(!dir_entry) return -1;
Считываем корневой каталог:
if(read_directory(root_cluster) < 0) return -1;
Проводим разбор полного пути файла и разделение каждого элемента на составляющие:
while(1) {
memset(tmp_name_buff, 0, SHORT_NAME);
memset((void *)&sn, 0, sizeof(struct split_name));
for(n = 0 ; n < SHORT_NAME; n++, i++) {
tmp_name_buff[n] = full_path[i];
if((tmp_name_buff[n] == ‘/’) || (tmp_name_buff[n] == ‘\0’)) {
i++;
break;
}
}
tmp_name_buff[n] = ‘\0’;
if(split_name(tmp_name_buff, &sn) < 0) {
printf(«not valid name\n»);
return -1;
}
if(get_dentry(&sn) < 0) {
printf(«No such file!\n»);
return -1;
}
Для получения стартового номера кластера в файловой системе FAT32 необходимо задействовать старшее слово номера первого кластера файла – поле starthi структуры dentry:
start_cluster = (((__u32)dentry.starthi << 16) | dentry.start);
Проверяем байт атрибутов:
if(dentry.attr & 0x10) { // это каталог
if(read_directory(start_cluster) < 0) return -1;
continue;
}
if(dentry.attr & 0x20) { // а это — файл
tmp_buff = (__u8 *)malloc(byte_per_cluster);
n = open(«clust», O_CREAT|O_RDWR, 0600);
if(n < 0) {
perror(«open»);
return -1;
}
printf(«file`s first cluster — 0x%X .. «, start_cluster);
for(i = 0; i < num; i++) {
memset(tmp_buff, 0, byte_per_cluster);
if(read_cluster(start_cluster, tmp_buff) < 0) return -1;
if(write(n, tmp_buff, byte_per_cluster) < 0) {
perror(«write»);
return -1;
}
next_cluster = fat32[start_cluster];
if(next_cluster == EOF_FAT32) {
free(tmp_buff);
close(n);
return ++i;
}
start_cluster = next_cluster;
}
return i;
}
}
}
Назначение следующих трёх функций – получить содержимое системной области, т.е. загрузочного сектора, структуры FSInfo и таблицы FAT32:
1) функция read_fbs() выполняет чтение загрузочного сектора:
int read_fbs()
{
if(pread64(hard, (__u8 *)&fbs, sizeof(fbs), start_seek) < 0) return -1;
return 0;
}
2) функция read_fs_info() считывает структуру FSInfo:
int read_fs_info()
{
__u64 seek = (__u64)fbs.info_sector * 512 + start_seek;
if(pread64(hard, (__u8 *)&fsinfo, sizeof(fsinfo), seek) < 0) return -1;
return 0;
}
3) функция read_fat32() считывает таблицу FAT32:
int read_fat32()
{
__u64 seek = (__u64)fbs.reserved * 512 + start_seek;
fat32 = (void *)malloc(fat32_size);
if(!fat32) return -1;
if(pread64(hard, (__u8 *)fat32, fat32_size, seek) < 0) return -1;
return 0;
}
Функция read_cluster() выполняет чтения кластера с указанным номером:
int read_cluster(__u32 cluster_num, __u8 *tmp_buff)
{
__u64 seek = (__u64)(byte_per_cluster) * (cluster_num — 2) + data_start + start_seek;
if(pread64(hard, tmp_buff, byte_per_cluster, seek) < 0) return -1;
return 0;
}
Чтением каталогов (в том числе и корневого) занимается функция read_directory():
int read_directory(__u32 start_cluster)
{
int i = 2;
__u32 next_cluster;
Параметры функции – стартовый кластер каталога. Считываем содержимое каталога в глобальный буфер dir_entry:
if(read_cluster(start_cluster, dir_entry) < 0) return -1;
next_cluster = fat32[start_cluster];
Если каталог занимает один кластер – выходим, если нет – увеличиваем размер памяти и продолжаем чтение:
if((next_cluster == EOF_FAT32) || (next_cluster == 0xFFFFFF8)) return 0;
for(; ;i++) {
start_cluster = next_cluster;
dir_entry = (__u8 *)realloc(dir_entry, i * byte_per_cluster);
if(!dir_entry) return -1;
if(read_cluster(start_cluster, (dir_entry + (i — 1) * byte_per_cluster)) < 0) return -1;
next_cluster = fat32[start_cluster];
if((next_cluster == EOF_FAT32) || (next_cluster == 0xFFFFFF8)) return 0;
}
return 0;
}
Последняя функция, которую мы рассмотрим, ищет в содержимом каталога элемент, соответствующий искомому файлу:
int get_dentry(struct split_name *sn)
{
int i = 0;
Указатель dir_entry настроен на область памяти, содержащую массив записей каталога, в котором мы собираемся искать файл (или каталог). Для поиска организуем цикл и найденную запись поместим в глобальную структуру dentry:
for(;;i++) {
memcpy((void *)&dentry, dir_entry + i * sizeof(dentry), sizeof(dentry));
if(!(memcmp(dentry.name, sn->name, sn->name_len)) &&
!(memcmp(dentry.ext, sn->ext, sn->ext_len)))
break;
if(!dentry.name[0]) return -1;
}
return 0;
}
На этом рассмотрение модуля чтения файла с раздела FAT32 завершим.
Исходные тексты модуля находятся в каталоге FAT32, файл fat32.c.
Отличия в организации хранения записей о файлах в каталогах для файловых систем FAT и EXT2
Несколько слов об отличиях в организации хранения записей о файлах в каталогах для файловых систем FAT и EXT2. Структура файловой системы EXT2 была рассмотрена в [3].
C FAT мы только что ознакомились – в ней все элементы каталога имеют фиксированную величину. При создании файла драйвер файловой системы ищет первую незанятую позицию и заполняет её информацией о файле. Если длина каталога не умещается в одном кластере, то под него отводится ещё один кластер и т. д.
Рассмотрим, как обстоят дела в EXT2.
Предположим, у нас есть раздел с файловой системой EXT2, размер блока равен 4096 байт. На этом разделе мы создаем каталог. Размер каталога будет равен размеру блока – 4096 байт. В каталоге операционная система сразу создаёт две записи – запись текущего и запись родительского каталогов. Запись текущего каталога займет 12 байт, в то время как длина записи родительского будет равна 4084 байта. Создадим в этом каталоге какой-нибудь файл. После этого в каталоге будут присутствовать три записи – запись текущего каталога длиной 12 байт, запись родительского каталога длиной уже 12 байт, и запись созданного файла длиной, как вы наверно догадались, 4072 байт. Если мы удалим созданный файл, длина записи родительского каталога опять возрастёт до 4084 байт.
Таким образом, при создании файла драйвер файловой системы EXT2 ищет в каталоге запись максимальной длины и расщепляет её, выделяя место для новой записи. Ну, а если всё-таки места не хватает, под каталог отводится ещё один блок, и длина каталога становится равной 8192 байт.
И в заключение – небольшая правка к статье «Архитектура файловой системы EXT2» [3].
Эта правка касается функции определения номера inode по имени файла get_i_num(). Старый вариант этой функции выглядел так:
int get_i_num(char *name)
{
int i = 0, rec_len = 0;
struct ext2_dir_entry_2 dent;
for(; i < 700; i++) {
memcpy((void *)&dent, (buff + rec_len), sizeof(dent));
if(!memcmp(dent.name, name, dent.name_len)) break;
rec_len += dent.rec_len;
}
return dent.inode;
}
Исправленный вариант:
int get_i_num(char *name)
{
/*
* Параметр функции — имя файла. Возвращаемое значение — номер inode файла.
*/
int rec_len = 0;
struct ext2_dir_entry_2 dent; // эта структура описывает формат записи корневого каталога:
/*
* В глобальном буфере buff находится массив записей каталога. Для определения порядкового номера inode файла необходимо найти
* в этом массиве запись с именем этого файла. Для этого организуем цикл:
*/
for(;;) {
/* Копируем в структуру dent записи каталога: */
memcpy((void *)&dent, (buff + rec_len), sizeof(dent));
/*
* Длина имени файла равная нулю означает, что мы перебрали все записи каталога
* и записи с именем нашего файла не нашли. Значит, пора возвращаться:
*/
if(!dent.name_len) return -1;
/* Поиск выполняется путем сравнения имен файлов. Если имена совпадают — выходим из цикла: */
if(!memcmp(dent.name, name, strlen(name))) break;
/* Если имена не совпали — смещаемся к следующей записи: */
rec_len += dent.rec_len;
}
/* В случае успеха возвращаем номер inode файла: */
return dent.inode;
}
Литература:
- В.Кулаков. Программирование на аппаратном уровне: специальный справочник. 2-е изд. / – СПб.: Питер, 2003 г. – 848 с.
- А.В.Гордеев, А.Ю.Молчанов. Системное программное обеспечение / – СПб.: Питер – 2002 г.
- Мешков В. Архитектура файловой системы ext2. – Журнал «Системный администратор», № 11(12), ноябрь 2003 г. – 26-32 с.
Мой мир
Вконтакте
Одноклассники
Google+
7.17. Физическая организация FAT-системы
Для обеспечения доступа приложений к файлам операционная система с файловой системой FAT использует следующие структуры:
- загрузочные секторы главного и дополнительных разделов;
- загрузочные секторы логических дисков (разделов);
- корневой каталог;
- область данных;
- цилиндр для выполнения диагностических операций чтения-записи.
На дискетах, в отличие от жесткого диска, нет загрузочных секторов главного и дополнительных разделов и диагностического цилиндра. Эти структуры создаются программой Fdisk, которая не применяется для дискет, так как они на разделы не разбиваются. Чтобы установить на один жесткий диск несколько операционных систем, его надо разбить на разделы. В загрузочном секторе главного раздела создается таблица списка разделов.
Загрузочный сектор главного раздела (называемый главной загрузочной записью – Master Boot Record – MBR) является первым сектором на жестком диске (цилиндр 0, головка 0, сектор 1) и состоит из двух элементов [10]:
- таблица главного раздела, содержащая список разделов (максимум четыре) и расположение загрузочных секторов соответствующих логических дисков (первая и последняя головки, первый и последний цилиндры с соответствующими значениями секторов, а также количество секторов);
- главный загрузочный код – небольшая программа, которая выполняется системой BIOS. Основная функция этого кода – передача управления в раздел, который обозначен как активный (загрузочный).
Загрузочный сектор раздела содержит:
- блок параметров диска, в котором содержится информация о разделе (размер, количество секторов, размер кластера, метка тома и др.);
- загрузочный код – программу, с которой начинается процесс загрузки операционной системы (для Ms-Dos и Windows 9x – файл Io.sys).
Загрузочные секторы логических дисков создаются программой Format. Они похожи на загрузочные диски разделов. Однако при загрузке выполняется код только того сектора, который находится в активном разделе.
Логический диск, отформатированный программой Fdisk, состоит из следующих областей (рис. 7.20):
- загрузочный сектор;
- основная FAT-таблица, содержащая информацию о размещении файлов и каталогов на диске;
- копия FAT-таблицы;
- корневой каталог – фиксированная область (16 Кбайт для жесткого диска), позволяющая хранить 512 записей о файлах и каталогах (каждая запись состоит из 32 байтов);
- область данных для размещения всех файлов и каталогов, кроме корневого каталога.
Первые две записи FAT зарезервированы и содержат информацию о самой FAT, все остальные указывают на соответствующие кластеры диска. Индексный указатель принимает значение, характеризующее состояние связанного с ним кластера (для FAT 16):
- кластер свободен (0000h);
- кластер используется (любое значение, кроме специальных);
- последний кластер файла (FFF8h – FFFFh);
- кластер поврежден (FFF7h);
- резервный кластер (FFF6h).
Рис.
7.20.
FAT-система
Размер FAT-таблицы определяется количеством кластера. Разрядность индексного указателя FAT-таблицы должна быть такой, чтобы можно было задать максимальный номер кластера диска определенного объема. В соответствии с разрядностью дискового указателя существуют несколько разновидностей FAT: FAT12, FAT16, FAT32 (соответственно 212, 216 и 232 кластеров). Тип используемой FAT определяется программой Fdisk, хотя и записываются они в процессе форматирования высокого уровня программы Format. На всех дискетах применяется FAT 12, на жестких дисках до 512 Мбайт – FAT16, на жестких дисках, имеющих большую емкость при использовании Windows 95 OSR2 и Windows98 – FAT 32 (вообще размер кластера может быть от 1 до 128 секторов или от 512 байт до 64 Кбайт). Максимальный размер раздела FAT16 ограничен объемом 4 Гбайт (216 = 65536 кластеров по 64 Кбайт). Максимальный размер раздела FAT 32 практически не ограничен (232 кластеров по 32 Кбайт).
За копией FAT-таблицы следует корневой каталог – база данных, содержащая информацию о записанных на диске данных. Каждая запись в ней имеет длину 32 байта и содержит всю информацию о файле, которой располагает операционная система. Формат записи приведен ниже.
Смещение | Описание | ||
---|---|---|---|
Hex | Dec | Длина поля | |
00h | 0 | 8 байт | Имя файла |
08h | 8 | 3 байт | Расширение файла |
0Bh | 11 | 1 байт | Атрибуты файла |
0Ch | 12 | 10 байт | Зарезервировано |
16h | 22 | 2 байт | Время создания |
18h | 24 | 2 байт | Дата создания |
1Ah | 26 | 2 байт | Начальный кластер |
1Ch | 28 | 4 байт | Размер файла в байтах |
Информация о расположении файла, то есть о расположении оставшихся кластеров, содержится в FAT-таблице. В процессе работы системы кластеры файла могут оказаться не в смежных областях, а будут чередоваться с кластерами других файлов. Однако эту цепочку кластеров легко выделить, зная начальный кластер файлов. На рис. 7.21 показан пример размещения двух файлов.
В корневом каталоге имеются записи не только о файлах, но и подкаталогах. Эти записи имеют точно такую же структуру, что и записи корневого каталога. Признак подкаталогов указывается в атрибутах файла, т.е. можно считать, что подкаталог – это специальный файл. Структура атрибутивного байта показана ниже.
Позиция бита в шестнадцатеричном формате | Значение | Описание | |||||||
---|---|---|---|---|---|---|---|---|---|
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | ||
0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 01h | Только чтение |
0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 02h | Скрытый |
0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 04h | Системный |
0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 08h | Метка тома |
0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 10h | Подкаталог |
0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 20h | Архивный (измененный) |
0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 40h | Зарезервировано |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 80h | Зарезервировано |
Рис.
7.21.
Пример размещения двух файлов
Файловые системы FAT 12 и FAT16 оперируют с именами файлов, составленных по схеме 8.3 (имя, расширение). В Windows 95 с появлением 32-разрядной виртуальной FAT—VFAT (Virtual file allocation table) поддерживаются имена длиной 255 символов (заметим, что изменился лишь программный код, поддерживающий FAT16, он стал 32-м). Для обеспечения обратной совместимости ОС создает его псевдоним, удовлетворяющий стандарту 8.3. Делается это следующим образом.
- Первые 3 символа после последней точки в длинном имени файла становятся расширением псевдонима.
- Первые шесть символов длинного имени файла, за исключением пробелов, которые игнорируются, преобразуются в символы верхнего регистра и становятся шестью символами стандартного имени файла. Недопустимые символы (+ , ; = [28] ), которые могут использоваться в Windows 95, преобразуются в символы подчеркивания.
- Добавляются символы ~1 (седьмой и восьмой) к псевдониму имени файла.
Если первые шесть символов нескольких файлов одни и те же, то добавляются символы ~2, ~3 и т.д.
VFAT хранит псевдонимы длинных имен в поле стандартных имен файлов записи каталога файла. Таким образом, все версии DOS и Windows могут получить доступ к файлу под длинным именем с помощью его псевдонима. Остается проблема: как хранить 255 символов имени файлов 32 байт записи каталога? Разработчики файловой системы решили эту проблему следующим образом: были добавлены дополнительные записи каталога для хранения длинных имен файлов. Чтобы предыдущие версии не повредили эти дополнительные записи каталога, VFAT устанавливает для них атрибуты, которые нельзя использовать для обычного файла: только для чтения, скрытый, системный и метка тома. Такие атрибуты DOS игнорирует, а следовательно, длинные имена файлов остаются нетронутыми. Подобным же образом решается проблема длинных имен в Windows NT/2000/2003/XP, применяющих для хранения имен двухбайтовый формат на каждый символ – Unicode.
Как уже отмечалось, выбор типа FAT-системы во многом определяется емкостью жесткого диска. При использовании FAT16 нельзя создать раздел емкостью более 2-х Гбайт. Для устранения этого ограничения фирма Microsoft разработала FAT 32. Она работает как FAT 16, но имеет отличие в организации хранения данных. Кроме того, FAT 32 можно установить с помощью программы Fdisk. Впервые FAT 32 была реализована в Windows 95 OEM Service Release 2 (OSR2). Она встроена и в Windows 98/Ме/NT/2000.
Основное преимущество FAT 32 – возможность использования 32-разрядных записей вместо 16-разрядных, что приводит к увеличению кластеров (вместо 216=65536) до 268 435 456 в разделе. Это значение в Windows 95 OSR2 эквивалентно 228, а не 232, поскольку 4 бита из 32 зарезервированы для других целей.
При работе в FAT 32 размер раздела может достигать 2 Tбайт при кластере размером 8, 16 или 32 Кбайт. Новая файловая система может иметь 232 кластеров размером 512 байт, а размер единичного файла может составить 4 Гбайт. Реально FAT 32 поддерживает максимальный размер тома до 32 Гбайт. Это связано с тем, что в Windows 2000 это ограничение обусловлено программой Format. Вообще максимально возможный том – 2 Tбайт при кластере 32 Кбайт.
Существует важное отличие FAT 32 от ее предшественниц – положение корневого каталога: он может располагаться в любом месте раздела и иметь любой раздел. Это обеспечивает динамическое изменение размера раздела. Независимые разработчики использовали это свойство. Так, фирма Power-Quest создала программу Partion Magic, позволяющую переопределять разделы после их создания.
Файловая система FAT 32 также использует преимущество двух копий FAT. Как и в FAT 16, в FAT 32 первая копия является основной и периодически копирует данные в дополнительную копию FAT. При проблемах с главной копией FAT системы переключаются в дополнительную копию, которая становится главной.
Примечание: программа Fdisk автоматически определяет размер кластера на основе выбранной файловой системы и размерам раздела. Однако существует недокументированный параметр команды Format, позволяющий явно указать размер кластера: Format/z:n, где n –размер кластера в байтах, кратный 512.
Файловые системы FAT
FAT16
FAT32
Файловая система NTFS
Атрибуты файлов в NTFS
Файловая система CDFS
Universal Disk Format
Сравнение файловых систем
Файловые системы FAT
Файловая система NTFS
Файловая система и скорость
Максимальный размер тома
Максимальный размер томов FAT
Максимальный размер томов NTFS
Одной из важнейших характеристик операционной системы помимо управления памятью, ресурсами компьютера и задачами является поддержка файловой системы — основного хранилища системной и пользовательской информации. В данном обзоре мы рассмотрим основные файловые системы, поддерживаемые в Microsoft Windows 2000, — FAT16, FAT32, NTFS, а также такие файловые системы, как CDFS и UDF. Каждая файловая система имеет свои достоинства и недостатки, которые мы обсудим ниже.
Начнем с того, что вспомним, какие файловые системы поддерживаются в различных операционных системах фирмы Microsoft (табл. 1).
Как видно из данной таблицы, наиболее популярной и широко используемой файловой системой является FAT. Именно с нее мы и начнем наше знакомство с файловыми системами Windows.
Файловые системы FAT
FAT16
Файловая система FAT16 начала свое существование еще во времена, предшествовавшие MS-DOS, и поддерживается всеми операционными системами Microsoft для обеспечения совместимости. Ее название File Allocation Table (таблица расположения файлов) отлично отражает физическую организацию файловой системы, к основным характеристикам которой можно отнести то, что максимальный размер поддерживаемого тома (жесткого диска или раздела на жестком диске) не превышает 4095 Мбайт. Во времена MS-DOS 4-гигабайтные жесткие диски казались несбыточной мечтой (роскошью были диски объемом 20-40 Мбайт), поэтому такой запас был вполне оправданным.
Том, отформатированный для использования FAT16, разделяется на кластеры. Размер кластера по умолчанию зависит от размера тома и может колебаться от 512 байт до 64 Кбайт. В табл. 2 показано, как размер кластера зависит от размера тома. Отметим, что размер кластера может отличаться от значения по умолчанию, но должен иметь одно из значений, указанных в табл. 2.
Не рекомендуется задействовать файловую систему FAT16 на томах больше 511 Мбайт, так как для относительно небольших по объему файлов дисковое пространство будет использоваться крайне неэффективно (файл размером в 1 байт будет занимать 64 Кбайт). Независимо от размера кластера файловая система FAT16 не поддерживается для томов больше 4 Гбайт.
На рис. 1 показано, как организован том при использовании файловой системы FAT16.
В файловой системе FAT16 кластеры могут иметь различное значение. Например, это может быть свободный (неиспользуемый) кластер, кластер, занятый файлом, дефектный кластер или последний кластер файла.
Единственным различием между корневым и другими каталогами является то, что первый располагается в определенном месте и имеет фиксированное число вхождений. Каждый каталог и файл используют одно или более вхождений. Например, если число фиксированных вхождений для корневого каталога равно 512 и создано 100 подкаталогов, в корневом каталоге можно создать не более 412 файлов (512 – 100).
Для каждого файла и каталога в файловой системе хранится информация (в табл. 3 приведены данные для коротких имен файлов).
В структуре каталогов файлу отводится первый незанятый кластер, доступный на томе. Номер начального кластера позволяет определить местонахождение файла: каждый кластер содержит указатель на следующий кластер или значение FFFF, указывающее на то, что это последний кластер в цепочке кластеров, занимаемых файлом. Расположение файлов по кластерам показано на рис. 2.
Как видно из рис. 2, в папке расположены три файла. Первый из них — FILE1.EXT занимает три кластера (файл не фрагментирован, кластеры 2, 3 и 4 расположены последовательно), второй файл — FILE2.EXT фрагментирован и располагается в кластерах 5, 6 и 8, а третий — FILE2.EXT занимает всего один кластер. Вхождение для каждого файла содержит адрес его начального кластера (2, 5 и 7 соответственно). Последний кластер каждого файла (4, 8 и 7) в качестве адреса следующего кластера содержит значение FFFF, указывающее на то, что это последний кластер для данного файла.
Так как все вхождения имеют одинаковый размер информационного блока, они различаются по байту атрибутов. Один из битов в данном байте может указывать, что это каталог, другой — что это метка тома. Для пользователей доступны четыре бита, позволяющих управлять атрибутами файла — архивный (archive), системный (system), скрытый (hidden) и доступный только для чтения (read-only) (рис. 3).
FAT32
Начиная с Microsoft Windows 95 OEM Service Release 2 (OSR2) в Windows появилась поддержка 32-битной FAT. Для систем на базе Windows NT эта файловая система впервые стала поддерживаться в Microsoft Windows 2000. Если FAT16 может поддерживать тома объемом до 4 Гбайт, то FAT32 способна обслуживать тома объемом до 2 Тбайт. Размер кластера в FAT32 может изменяться от 1 (512 байт) до 64 секторов (32 Кбайт). Для хранения значений кластеров FAT32 требуется 4 байт (32 бит, а не 16, как в FAT16). Это означает, в частности, что некоторые файловые утилиты, рассчитанные на FAT16, не могут работать с FAT32.
Основным отличием FAT32 от FAT16 является то, что изменился размер логического раздела диска. FAT32 поддерживает тома объемом до 127 Гбайт. При этом, если при использовании FAT16 с 2-гигабайтными дисками требовался кластер размером в 32 Кбайт, то в FAT32 кластер размером в 4 Кбайт подходит для дисков объемом от 512 Мбайт до 8 Гбайт (табл. 4).
Это соответственно означает более эффективное использование дискового пространства — чем меньше кластер, тем меньше места требуется для хранения файла и, как следствие, диск реже становится фрагментированным.
При применении FAT32 максимальный размер файла может достигать 4 Гбайт минус 2 байта. Если при использовании FAT16 максимальное число вхождений в корневой каталог ограничивалось 512, то FAT32 позволяет увеличить это число до 65 535.
FAT32 накладывает ограничения на минимальный размер тома — он должен быть не менее 65 527 кластеров. При этом размер кластера не может быть таким, чтобы FAT занимала более 16 Мбайт–64 Кбайт / 4 или 4 млн. кластеров.
При использовании длинных имен файлов данные, необходимые для доступа из FAT16 и FAT32, не перекрываются. При создании файла с длинным именем Windows создает соответствующее имя в формате 8.3 и одно или более вхождений в каталог для хранения длинного имени (по 13 символов из длинного имени файла на каждое вхождение). Каждое последующее вхождение хранит соответствующую часть имени файла в формате Unicode. Такие вхождения имеют атрибуты «идентификатор тома», «только чтение», «системный» и «скрытый» — набор, который игнорируется MS-DOS; в этой операционной системе доступ к файлу осуществляется по его «псевдониму» в формате 8.3.
Файловая система NTFS
В состав Microsoft Windows 2000 входит поддержка новой версии файловой системы NTFS, которая, в частности, обеспечивает работу с сервисами каталогов Active Directory, точки пересчета (reparse points), средства защиты информации, контроль за доступом и ряд других возможностей.
Как и при использовании FAT, основной информационной единицей в NTFS является кластер. В табл. 5 показаны размеры кластеров по умолчанию для томов различной емкости.
При формировании файловой системы NTFS программа форматирования создает файл Master File Table (MTF) и другие области для хранения метаданных. Метаданные используются NTFS для реализации файловой структуры. Первые 16 записей в MFT зарезервированы самой NTFS. Местоположение файлов метаданных $Mft и $MftMirr записано в загрузочном секторе диска. Если первая запись в MFT повреждена, NTFS считывает вторую запись для нахождения копии первой. Полная копия загрузочного сектора располагается в конце тома. В табл. 6 перечислены основные метаданные, хранимые в MFT.
Остальные записи MFT содержат записи для каждого файла и каталога, расположенных на данном томе.
Обычно один файл использует одну запись в MFT, но если у файла большой набор атрибутов или он становится слишком фрагментированным, то для хранения информации о нем могут потребоваться дополнительные записи. В этом случае первая запись о файле, называемая базовой записью, хранит местоположение других записей. Данные о файлах и каталогах небольшого размера (до 1500 байт) полностью содержатся в первой записи.
Атрибуты файлов в NTFS
Каждый занятый сектор на NTFS-томе принадлежит тому или иному файлу. Даже метаданные файловой системы являются частью файла. NTFS рассматривает каждый файл (или каталог) как набор файловых атрибутов. Такие элементы, как имя файла, информация о его защите и даже данные в нем, являются атрибутами файла. Каждый атрибут идентифицируется кодом определенного типа и, опционально, именем атрибута.
Если атрибуты файла вмещаются в файловую запись, они называются резидентными атрибутами. Такими атрибутами всегда являются имя файла и дата его создания. В тех случаях, когда информация о файле слишком велика, чтобы вместиться в одну MFT-запись, некоторые атрибуты файла становятся нерезидентными. Резидентные атрибуты хранятся в одном или более кластерах и представляют собой поток альтернативных данных для текущего тома (об этом — чуть ниже). Для описания местонахождения резидентных и нерезидентных атрибутов NTFS создает атрибут Attribute List.
В табл. 7 показаны основные атрибуты файлов, определенные в NTFS. В будущем этот список может быть расширен.
Файловая система CDFS
В Windows 2000 обеспечивается поддержка файловой системы CDFS, отвечающей стандарту ISO’9660, описывающему расположение информации на CD-ROM. Поддерживаются длинные имена файлов в соответствии с ISO’9660 Level 2.
При создании CD-ROM для использования под управлением Windows 2000 следует иметь в виду следующее:
- все имена каталогов и файлов должны содержать менее 32 символов;
- все имена каталогов и файлов должны состоять только из символов верхнего регистра;
- глубина каталогов не должна превышать 8 уровней от корня;
- использование расширений имен файлов не обязательно.
Universal Disk Format
Поддержка файловой системы UDF является одним из новшеств в Windows 2000. Universal Disk Format — это файловая система, отвечающая стандарту ISO’13346 и используемая для обмена данными с накопителями CD-ROM и DVD. В настоящее время поддерживаются только диски версий UDF 1.02 и 1.50.
На этом мы закончим рассмотрение файловых систем, поддерживаемых в Microsoft
Windows 2000, и перейдем к обсуждению их достоинств и недостатков, а также приведем
рекомендации по их использованию.
Сравнение файловых систем
Под управлением Microsoft Windows 2000 возможно использование файловых систем
FAT16, FAT32, NTFS или их комбинаций. Выбор операционной системы зависит от
следующих критериев:
- того, как используется компьютер;
- аппаратной платформы;
- размера и числа жестких дисков;
- безопасности информации
Файловые системы FAT
Как вы уже могли заметить, цифры в названии файловых систем — FAT16 и FAT32
— указывают на число бит, необходимых для хранения информации о номерах кластеров,
используемых файлом. Так, в FAT16 применяется 16-битная адресация и, соответственно,
возможно использование до 216 адресов. В Windows 2000 первые четыре бита таблицы
расположения файлов FAT32 необходимы для собственных нужд, поэтому в FAT32 число
адресов достигает 228.
В табл. 8 показаны размеры кластеров для файловых
систем FAT16 и FAT32.
Помимо существенных отличий в размере кластера FAT32 также позволяет корневому
каталогу расширяться (в FAT16 число вхождений ограничено 512 и может быть даже
ниже при использовании длинных имен файлов).
Преимущества FAT16
Среди преимуществ FAT16 можно отметить следующие:
- файловая система поддерживается операционными системами MS-DOS, Windows
95, Windows 98, Windows NT, Windows 2000, а также некоторыми операционными
системами UNIX; - существует большое число программ, позволяющих исправлять ошибки в этой
файловой системе и восстанавливать данные; - при возникновении проблем с загрузкой с жесткого диска система может быть
загружена с флоппи-диска; - данная файловая система достаточно эффективна для томов объемом менее 256
Мбайт.
Недостатки FAT16
К основным недостаткам FAT16 относятся:
- корневой каталог не может содержать более 512 элементов. Использование длинных
имен файлов существенно сокращает число этих элементов; - FAT16 поддерживает не более 65 536 кластеров, а так как некоторые кластеры
зарезервированы операционной системой, число доступных кластеров — 65 524.
Каждый кластер имеет фиксированный размер для данного логического устройства.
При достижении максимального числа кластеров при их максимальном размере (32
Кбайт) максимальный объем поддерживаемого тома ограничивается 4 Гбайт (под
управлением Windows 2000). Для поддержания совместимости с MS-DOS, Windows
95 и Windows 98 объем тома под FAT16 не должен превышать 2 Гбайт; - не поддерживается резервная копия загрузочного сектора;
- в FAT16 не поддерживается встроенная защита файлов и их сжатие;
- на дисках большого объема теряется много места за счет того, что используется
максимальный размер кластера. Место под файл выделяется исходя из размера
не файла, а кластера.
Преимущества FAT32
Среди преимуществ FAT32 можно отметить следующие:
- выделение дискового пространства выполняется более эффективно, особенно
для дисков большого объема; - корневой каталог в FAT32 представляет собой обычную цепочку кластеров и
может находиться в любом месте диска. Благодаря этому FAT32 не накладывает
никаких ограничений на число элементов в корневом каталоге; - за счет использования кластеров меньшего размера (4 Кбайт на дисках объемом
до 8 Гбайт) занятое дисковое пространство обычно на 10-15% меньше, чем под
FAT16; - FAT32 является более надежной файловой системой. В частности, она поддерживает
возможность перемещения корневого каталога и использования резервной копии
FAT. Помимо этого загрузочная запись содержит ряд критичных для файловой системы
данных.
Недостатки FAT32
Основные недостатки FAT32:
- размер тома при использовании FAT32 под Windows 2000 ограничен 32 Гбайт;
- тома FAT32 недоступны из других операционных систем — только из Windows
95 OSR2 и Windows 98; - не поддерживается резервная копия загрузочного сектора;
- в FAT32 не поддерживается встроенная защита файлов и их сжатие.
Файловая система NTFS
При работе в Windows 2000 Microsoft рекомендуется отформатировать все разделы
жесткого диска под NTFS, за исключением тех конфигураций, когда используется
несколько операционных систем (кроме Windows 2000 и Windows NT). Применение
NTFS вместо FAT позволяет использовать функции, доступные в NTFS. К ним, в частности,
относятся:
- возможность восстановления. Эта возможность «встроена» в файловую систему.
NTFS гарантирует сохранность данных за счет того, что использует протокол
и некоторые алгоритмы восстановления информации. В случае системного сбоя
NTFS использует протокол и дополнительную информацию для автоматического восстановления
целостности файловой системы; - сжатие информации. Для томов NTFS Windows 2000 поддерживает сжатие отдельных
файлов. Такие сжатые файлы могут использоваться Windows-приложениями без предварительной
распаковки, которая происходит автоматически при чтении из файла. При закрытии
и сохранении файл снова упаковывается; - помимо этого можно выделить следующие преимущества NTFS:
— некоторые функции операционной системы требуют наличия NTFS;
— скорость доступа намного выше — NTFS минимизирует число обращений к диску,
требуемых для нахождения файла;
— защита файлов и каталогов. Только на томах NTFS возможно задание атрибутов
доступа к файлам и папкам;
— при использовании NTFS Windows 2000 поддерживает тома объемом до 2 Тбайт;
— файловая система поддерживает резервную копию загрузочного сектора — она
располагается в конце тома;
— NTFS поддерживает систему шифрования Encrypted File System (EFS), обеспечивающую
защиту от неавторизованного доступа к содержимому файлов;
— при использовании квот можно ограничить объем дискового пространства, занимаемого
пользователями.
Недостатки NTFS
Говоря о недостатках файловой системы NTFS, следует отметить, что:
- NTFS-тома недоступны в MS-DOS, Windows 95 и Windows 98. Помимо этого ряд
функций, реализованных в NTFS под Windows 2000, недоступен в Windows 4.0 и
более ранних версиях; - для томов небольшого объема, содержащих много файлов небольшого размера,
возможно снижение производительности по сравнению с FAT.
Файловая система и скорость
Как мы уже выяснили, для томов небольшого объема FAT16 или FAT32 обеспечивает
более быстрый доступ к файлам по сравнению с NTFS, так как:
- FAT обладает более простой структурой;
- размер каталогов меньше;
- FAT не поддерживает защиту файлов от несанкционированного доступа — системе
не нужно проверять права доступа к файлам.
NTFS минимизирует число обращений к диску и время, необходимое для нахождения
файла. Кроме того, если размер каталога достаточно мал, чтобы поместиться в
одной записи MFT, вся запись считывается за один раз.
Одно вхождение в FAT содержит номер кластера для первого кластера каталога.
Для просмотра файла FAT требуется поиск по всей файловой структуре.
Сравнивая скорость операций, выполняемых для каталогов, содержащих короткие
и длинные имена файлов, следует учитывать, что скорость операций для FAT зависит
от самой операции и размера каталога. Если FAT ищет несуществующий файл, поиск
выполняется по всему каталогу — эта операция занимает больше времени, чем поиск
по структуре, основанной на B-деревьях, используемой в NTFS. Среднее время,
необходимое для поиска файла, в FAT выражается как функция от N/2, в NTFS —
как log N, где N — это число файлов.
Ряд следующих факторов влияет на скорость чтения и записи файлов под управлением
Windows 2000:
- фрагментация файла. Если файл сильно фрагментирован, NTFS обычно требуется
меньше обращений к диску, чем FAT для нахождения всех фрагментов; - размер кластера. Для обеих файловых систем размер кластера по умолчанию
зависит от объема тома и всегда выражается степенью числа 2. Адреса в FAT16 —
16-битные, в FAT32 — 32-битные, в NTFS — 64-битные; - размер кластера по умолчанию в FAT базируется на том факте, что таблица
расположения файлов может иметь не более 65 535 вхождений — размер кластера
представляет собой функцию от объема тома, деленного на 65 535. Таким образом,
размер кластера по умолчанию для тома FAT всегда больше, чем размер кластера
для тома NTFS того же объема. Отметим, что больший размер кластера для томов
FAT означает, что тома FAT могут быть менее фрагментированными; - расположение файлов небольшого размера. При использовании NTFS файлы небольшого
размера содержатся в MFT-записи. Размер файла, помещающегося в одну запись
MFT, зависит от числа атрибутов этого файла.
Максимальный размер тома
Максимальный размер тома зависит от используемой файловой системы. Windows
2000 позволяет форматировать тома для трех файловых систем: FAT16, FAT32 и NTFS.
Максимальный размер томов FAT
Как мы уже отмечали, FAT16 поддерживает до 65 535 кластеров на одном томе.
Из этого факта вытекают ограничения, показанные в табл.
9.
Под управлением Windows NT и Windows 2000 размер кластера FAT16 для томов размером
от 2 до 4 Гбайт равен 64 Кбайт. Этот размер кластера используется для обеспечения
совместимости с некоторыми приложениями (например, с программами установки,
которые неверно высчитывают объем свободного пространства). Поэтому рекомендуется
использовать FAT32 для томов размером от 2 до 4 Гбайт.
FAT32 работает с томами, на которых есть как минимум 65 527 кластеров, а максимальное
число кластеров, поддерживаемых этой файловой системой для одного тома, — 4
177 918. Windows 2000 позволяет создавать тома размером до 32 Гбайт.
В табл. 10 показаны основные ограничения FAT32.
Максимальный размер томов NTFS
Теоретически NTFS поддерживает тома с числом кластеров до 232. Но тем не менее
помимо отсутствия жестких дисков такого объема существуют и другие ограничения
на максимальный размер тома.
Одним из таких ограничений является таблица разделов. Индустриальные стандарты
ограничивают размер таблицы разделов 232 секторами. Другим ограничением является
размер сектора, который обычно равен 512 байт. Поскольку размер сектора может
измениться в будущем, текущий размер дает ограничение на размер одного тома —
2 Тбайт (232 x 512 байт = 241). Таким образом, 2 Тбайт является практическим
пределом для физических и логических томов NTFS.
В табл. 11 показаны основные ограничения NTFS.
Управление доступом к файлам и каталогам
При использовании томов NTFS можно устанавливать права доступа к файлам и каталогам.
Эти права доступа указывают, какие пользователи и группы имеют доступ к ним
и какой уровень доступа допустим. Такие права доступа распространяются как на
пользователей, работающих за компьютером, на котором располагаются файлы, так
и на пользователей, обращающихся к файлам через сеть, когда файл располагается
в каталоге, открытом для удаленного доступа.
Под NTFS можно также устанавливать разрешения на удаленный доступ, объединяемые
с разрешениями на доступ к файлам и каталогам. Помимо этого файловые атрибуты
(только чтение, скрытый, системный) также ограничивают доступ к файлу.
Под управлением FAT16 и FAT32 тоже возможно устанавливать атрибуты файлов,
но они не обеспечивают права доступа к файлам.
В версии NTFS, используемой в Windows 2000, появился новый тип разрешения на
доступ — наследуемые разрешения. Вкладка Security содержит опцию Allow
inheritable permissions from parent to propagate to this file object,
которая по умолчанию находится в активном состоянии. Данная опция существенно
сокращает время, требуемое на изменение прав доступа к файлам и подкаталогам.
Например, для изменения прав доступа к дереву, содержащему сотни подкаталогов
и файлов, достаточно включить эту опцию — в Windows NT 4 необходимо изменить
атрибуты каждого отдельного файла и подкаталога.
На рис. 5 показаны диалоговая панель Properties и вкладка
Security (раздел Advanced) — перечислены расширенные права доступа к файлу.
Напомним, что для томов FAT можно управлять доступом только на уровне томов
и такой контроль возможен только при удаленном доступе.
Сжатие файлов и каталогов
В Windows 2000 поддерживается сжатие файлов и каталогов, расположенных на NTFS-томах.
Сжатые файлы доступны для чтения и записи любыми Windows-приложениями. Для этого
нет необходимости в их предварительной распаковке. Используемый алгоритм сжатия
схож с тем, который используется в DoubleSpace (MS-DOS 6.0) и DriveSpace (MS-DOS
6.22), но имеет одно существенное отличие — под управлением MS-DOS выполняется
сжатие целого первичного раздела или логического устройства, тогда как под NTFS
можно упаковывать отдельные файлы и каталоги.
Алгоритм сжатия в NTFS разработан с учетом поддержки кластеров размером до
4 Кбайт. Если величина кластера больше 4 Кбайт, функции сжатия NTFS становятся
недоступными.
Самовосстановление NTFS
Файловая система NTFS обладает способностью самовосстановления и может поддерживать
свою целостность за счет использования протокола выполняемых действий и ряда
других механизмов.
NTFS рассматривает каждую операцию, модифицирующую системные файлы на NTFS-томах,
как транзакцию и сохраняет информацию о такой транзакции в протоколе. Начатая
транзакция может быть либо полностью завершена (commit), либо откатывается (rollback).
В последнем случае NTFS-том возвращается в состояние, предшествующее началу
транзакции. Для того чтобы управлять транзакциями, NTFS записывает все операции,
входящие в транзакцию, в файл протокола, перед тем как осуществить запись на
диск. После того как транзакция завершена, все операции выполняются. Таким образом,
под управлением NTFS не может быть незавершенных операций. В случае дисковых
сбоев незавершенные операции просто отменяются.
Под управлением NTFS также выполняются операции, позволяющие «на лету» определять
дефектные кластеры и отводить новые кластеры для файловых операций. Этот механизм
называется cluster remapping.
В данном обзоре мы рассмотрели различные файловые системы, поддерживаемые в
Microsoft Windows 2000, обсудили устройство каждой из них, отметили их достоинства
и недостатки. Наиболее перспективной является файловая система NTFS, которая
обладает большим набором функций, недоступных в других файловых системах. Новая
версия NTFS, поддерживаемая Microsoft Windows 2000, обладает еще большей функциональностью
и поэтому рекомендуется для использования при установке операционной системы
Win 2000.
КомпьютерПресс 7’2000