60 какую информацию содержит fat. Файловая система FAT. Различные версии FAT

Файловая система FAT (File Allocation Table - таблица размещения файлов) по­лучила свое название благодаря простой таблице, в которой указываются:

Непосредственно адресуемые участки логического диска, отведенные для раз­мещения в них файлов или их фрагментов;

Свободные области дискового пространства;

Дефектные области диска (эти области содержат дефектные участки и не га­рантируют чтение и запись данных без ошибок).

В файловой системе FAT дисковое пространство любого логического диска де­лится на две области (рис. 6.1): системную область и область данных.

Рис. 6.1. Структура логического диска в FAT

Системная область логического диска создается и инициализируется при форма­тировании, а в последующем обновляется при работе с файловой структурой. Об­ласть данных логического диска содержит обычные файлы и файлы-каталоги; эти объекты образуют иерархию, подчиненную корневому каталогу. Элемент катало-


Файловая система FAT________________________________________________ 167

га описывает файловый объект, который может быть либо обычным файлом, либо файлом-каталогом. Область данных, в отличие от системной области, доступна через пользовательский интерфейс операционной системы. Системная область состоит из следующих компонентов (расположенных в логическом адресном про­странстве друг за другом):

Загрузочной записи (Boot Record, BR);

Зарезервированных секторов (Reserved Sectors, ResSec);

Таблицы размещения файлов (File Allocation Table, FAT);

Корневого каталога (Root Directory, RDir).

Таблица размещения файлов

Таблица размещения файлов является очень важной информационной структу­рой. Можно сказать, что она представляет собой адресную карту области данных, в которой описывается и состояние каждого участка области данных, и принад­лежность его к тому или иному файловому объекту.

Всю область данных разбивают на так называемые кластеры. Кластер представля­ет собой один или несколько смежных секторов в логическом дисковом адресном пространстве (точнее - только в области данных). Кластер - это минимальная адресуемая единица дисковой памяти, выделяемая файлу (или некорневому ката­логу). Кластеры введены для того, чтобы уменьшить количество адресуемых еди­ниц в области данных логического диска.

Каждый файл занимает целое число кластеров. Последний кластер при этом мо­жет быть задействован не полностью, что при большом размере кластера может приводить к заметной потере дискового пространства. На дискетах кластер зани­мает один или два сектора, а на жестких дисках его размер зависит от объема раз­дела (табл. 6.1). В таблице FAT кластеры, принадлежащие одному файлу (или файлу-каталогу), связываются в цепочки. Для указания номера кластера в файло­вой системе FAT 16 используется 16-разрядное слово, следовательно, можно иметь до 2 10 = 65 536 кластеров (с номерами от 0 до 65 535).

Таблица 6.1 . Соотношения между размером раздела и размером кластеров в FAT16

Емкость раздела, Мбайт Количество секторов в кластере Размер кластеров, Кбайт

Заметим, что в Windows NT/2000/XP разделы файловой системы FAT могут иметь размер до 4097 Мбайт. В этом случае кластер будет объединять уже 128 секторов.

Номер кластера всегда относится к области данных диска (пространству, зарезер­вированному для файлов и подкаталогов). Номера кластеров соответствуют эле-


168____________________________________________ Глава 6, Файловые системы

ментам таблицы размещения файлов. Первый допустимый номер кластера всегда начинается с 2.

Логическое разбиение области данных на кластеры как совокупности секторов взамен использования одиночных секторов имеет следующий смысл:

Прежде всего, уменьшается размер самой таблицы FAT; - уменьшается возможная фрагментация файлов;

Ускоряется доступ к файлу, так как в несколько раз сокращается длина цепочек фрагментов дискового пространства, выделенных для него.

Однако слишком большой размер кластера ведет к неэффективному использова­нию области данных, особенно в случае большого количества маленьких файлов. Как мы только что заметили, в среднем на каждый файл теряется около половины кластера. Из табл. 6.1 следует, что при размере кластера в 32 сектора (объем разде­ла при этом - от 512 до 1023 Мбайт), то есть 16 Кбайт, средняя величина потерь на файл равняется 8 Кбайт, и при нескольких тысячах файлов 1 потери могут со­ставлять более 100 Мбайт. Поэтому в современных файловых системах размеры кластеров ограничиваются (обычно от 512 байт до 4 Кбайт), либо предоставляет­ся возможность выбирать размер кластера.

Достаточно наглядно идею файловой системы, использующей таблицу размеще­ния файлов, иллюстрирует рис. 6.2.

Рис. 6.2. Иллюстрация основной концепции FAT

Из рисунка видно, что файл MYFILE.TXT размещается, начиная с восьмого кластера. Всего файл MYFILE.TXT занимает 12 кластеров. Цепочка (chain) кластеров для на­шего примера может быть записана следующим образом: 8, 9,0А, 0В, 15,16,17,19,

1 Например, число 10 000-15 000 файлов (или даже более, особенно когда файлы небольшого разме­ра) на логическом диске с объемом в 1000 Мбайт встречается достаточно часто.


Файловая система FAT 169

1А, 1B, 1С, 1D. Кластер с номером 18 помечен специальным кодом F7 как плохой (bad), он не может быть использован для размещения данных. При форматирова­нии обычно проверяется поверхность магнитного диска, и те сектора, при конт­рольном чтении с которых происходили ошибки, помечаются в FAT как плохие. Кластер 1D помечен кодом FF как конечный (последний в цепочке) кластер, принадлежащий данному файлу. Свободные (незанятые) кластеры помечаются кодом 00; при выделении нового кластера для записи файла берется первый сво­бодный кластер. Возможные значения, которые могут приписываться элементам таблицы FAT, приведены в табл. 6.2.

Таблица 6.2. Значения элементов FAT

Значение Описание

OOOOh Свободный кластер

fffOh-fff6h Зарезервированный кластер

fff7h Плохой кластер

fffSh-ffffh Последний кластер в цепочке

0002h-ffefh Номер следующего кластера в цепочке

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

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

В связи с чрезвычайной важностью таблицы FAT она обычно хранится в двух иден­тичных экземплярах, второй из которых непосредственно следует за первым. Об­новляются копии FAT одновременно, используется же только первый экземпляр. Если он по каким-либо причинам окажется разрушенным, то произойдет обраще­ние ко второму экземпляру. Так, например, утилита проверки и восстановления файловой структуры ScanDisk из ОС Windows 9x при обнаружении несоответствия первичной и резервной копии FAT предлагает восстановить главную таблицу, ис­пользуя данные из копии.

Корневой каталог отличается от обычного файла-каталога тем, что он помимо раз­мещения в фиксированном месте логического диска имеет еще и фиксированное число элементов. Для каждого файла и каталога в файловой системе хранится ин­формация в соответствии со структурой, представленной в табл. 6.3.

Для работы с данными на магнитных дисках в системах DOS, которые имеют файло­вую систему FAT, удобно использовать широко известную утилиту Disk Editor из


170___________________________________________ Глава 6. Файловые системы

комплекта утилит Питера Нортона. У нее много достоинств. Прежде всего, она ком­пактна, легко размещается на системной дискете с MS DOS, снабжена встроенной системой подсказок и необходимой справочной информацией. Используя ее, можно сохранять, модифицировать и восстанавливать загрузочную запись, восстанавливать таблицу FAT в случае ее повреждения, а также выполнять много других операций. Основными недостатками этой программы на сегодняшний день являются ограниче­ния на размеры диска и разделов и отсутствие поддержки работы с такими распрост­раненными файловыми системами, как FAT32 и NTFS. Вместо нее теперь часто ис­пользуют утилиту Partition Magic, однако наилучшей альтернативой этой программе на сегодняшний день можно считать утилиту Администратор дисков от Acronis.

Таблица 6.3. Структура элемента каталога

Размер поля данных, байт Содержание поля

11 Имя файла или каталога

1 Атрибуты файла

1 Резервное поле

3 Время создания

2 Дата создания

2 Дата последнего доступа

2 Зарезервировано

2 Время последней модификации

2 Дата последней модификации

2 Номер начального кластера в FAT

4 Размер файла

Структура загрузочной записи DOS

Сектор, содержащий системный загрузчик DOS, является самым первым на логи­ческом диске С:. Напомним, что на дискете системный загрузчик размещается в са­мом первом секторе; его физический адрес равен 0-0-1. Загрузочная запись состо­ит, как мы уже знаем, из двух частей: блока параметров диска (Disk Parameter Block, DPB) и системного загрузчика (System Bootstrap, SB). Блок параметров диска слу­жит для идентификации физического и логического форматов логического диска, а системный загрузчик играет существенную роль в процессе загрузки DOS. Эта информационная структура приведена в табл. 6.4.

Первые два байта загрузочной записи занимает команда безусловного перехода (JMP) на программу SB. Третий байт содержит код 90Н (NOP - нет операции). Да­лее располагается восьмибайтовый системный идентификатор, включающий ин­формацию о фирме-разработчике и версии операционной системы. Затем следует блок параметров диска, а после него - системный загрузчик.

Для работы с загрузочной записью DOS, как и с другими служебными информа­ционными структурами, удобно использовать уже упомянутую программу Disk


Файловая система FAT________________________________________________ 171

Editor из комплекта утилит Питера Нортона. Используя ее, можно сохранять, мо­дифицировать и восстанавливать загрузочную запись, а также выполнять много других операций. Достаточно подробно работа с этой утилитой описана в .

Таблица 6.4. Структура загрузочной записи для FAT16

Смещение поля, Длина поля, Обозначение Содержимое поля
байт байт поля

ООН (0) 3 JUMP 3EH Безусловный переход на начало

системного загрузчика

ОЗН (3) 8 Системный идентификатор

ОВН (11) 2 SectSize Размер сектора, байт

ООН (13) 1 ClastSize Число секторов в кластере

0ЕН(14) 2 ResSecs Число зарезервированных секторов

10Н (16) 1 FATcnt Число копий FAT

11Н (17) 2 RootSize Максимальное число элементов Rdir

13Н (19) 2 TotSecs Число секторов на логическом диске,

если его размер не превышает 32 Мбайт; иначе 0000Н

15Н (21) 1 Media Дескриптор носителя

16Н(22) 2 FATsize Размер FAT, секторов

18Н(24) 2 TrkSecs Число секторов на дорожке

1АН(26) 2 HeadCnt Число рабочих поверхностей

1СН(28) 4 HidnSecs Число скрытых секторов

20Н (32) 4 Число секторов на логическом диске,

если его размер превышает 32 Мбайт

24Н (36) 1 Тип логического диска (ООН - гибкий,

80Н - жесткий)

25Н (37) 1 Зарезервировано

26Н (38) 1 Маркер с кодом 29Н

27Н (39) 4 Серийный номер тома 1

2ВН (43) 11 Метка тома

36Н (54) 8 Имя файловой системы

ЗЕН (62) Системный загрузчик

1FEH (510) 2 Сигнатура (слово АА55Н)

1 Том (volume) представляет собой единое логическое адресное пространство. Томом может быть обыч­ный логический диск либо несколько дисковых пространств.

ВЛАДИМИР МЕШКОВ

Архитектура файловой системы 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 изображена на рисунке.

В файловой системе 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.
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

Загрузочный сектор

В первом секторе логического диска с системой 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 1 0x26 1 Признак расширенной загрузочной записи (0x29) 0x27 4 Номер логического диска 0x2B 11 Метка диска 0x36 8 Текстовая строка с аббревиатурой типа файловой системы

Таблица 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

#include

#include

#include

#include

#include "split.h"

Заголовочный файл split.h имеет следующее содержание:

#include

#define SHORT_NAME 13 // максимальная длина короткого имени файла

struct split_name {

U8 name; // имя файла

U8 ext; // расширение файла

Int name_len, // длина имени файла

Ext_len; // длина расширения файла

Cтруктура split_name предназначена для хранения составных частей короткого имени файла (имени и расширения) и их длин.

В заголовочном файле определены структурные типы, описывающие основные компоненты файловой системы FAT – загрузочный сектор, сектор FSInfo, структуры элементов каталога для короткого и длинного имён файлов.

Рассмотрим кратко поля, которые входят в каждую из этих структур.

    1. Структура загрузочного сектора struct fat_boot_sector:
      • __s8 system_id – системный идентификатор;
      • __u8 sector_size – размер сектора в байтах;
      • __u8 cluster_size – размер кластера в секторах;
      • __u16 reserved – число резервных секторов в резервной области раздела;
      • __u8 fats – количество копий FAT;
      • __u8 dir_entries – количество 32-байтных дескрипторов файлов в корневом каталоге;
      • __u8 sectors – число секторов на разделе; если это поле равно 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:

  1. Структура сектора FSInfo struct fat_boot_fsinfo:
    • __u32 signature1 – сигнатура 0x41615252;
    • __u32 signature2 – сигнатура 0x61417272;
    • __u32 free_clusters – количество свободных кластеров. Если поле содержит -1, поиск свободных кластеров нужно начинать с кластера номер 2.
  2. Структура элемента каталога короткого имени struct msdos_dir_entry:
    • __s8 name,ext – имя и расширение файла;
    • __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 – размер файла (в байтах).
  3. Структура элемента каталога длинного имени:
    • __u8 id – номер элемента;
    • __u8 name0_4 – символы 1 – 5 имени;
    • __u8 attr – атрибуты файла;
    • __u8 alias_checksum – контрольная сумма короткого имени;
    • __u8 name5_10 – символы 6 – 11 имени;
    • __u8 name11_12 – символы 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; // размер корневого каталога

U16 byte_per_cluster; // размер кластера в байтах

U16 next_cluster; // очередной кластер в цепочке

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; // буфер для временного хранения составных элементов полного пути файла

Static int i = 1;

Int n;

U8 *tmp_buff;

U16 start_cluster, next_cluster;

Параметры функции мы перечислили при рассмотрении функции main.

Подготовительные операции – обнуляем буфер tmp_name_buff и структуру struct split_name sn:

Первым символом в абсолютном путевом имени файла должен быть прямой слэш (/). Проверяем это:

Считываем с раздела загрузочный сектор:

If(read_fbs() < 0) return -1;

Считанный загрузочный сектор находится сейчас в глобальной структуре struct fat_boot_sector fbs. Скопируем из этой структуры размер сектора, число записей в корневом каталоге и общее число секторов на разделе:

Определим размер кластера в байтах:

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

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++) {

If((tmp_name_buff[n] == "/") || (tmp_name_buff[n] == "?")) {

I++;

Break;

Tmp_name_buff[n] = "?";

Заполняем структуру struct split_name sn соответствующей информацией. Заполнение выполняет функция split_name, при этом выполняется проверка имени файла на соответствие формату «8.3»:

< 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;

Для считывания кластеров файла организуем цикл:

For(i = 0; i < num; i++) {

Считываем содержимое кластера в буфер tmp_buff и сохраняем его в отдельном файле:

< 0) return -1;

< 0) {

Perror("write");

Close(n);

Return -1;

Считываем из FAT16 номер следующего кластера, занятого под данный файл. Если это последний кластер – прерываем цикл и возвращаемся в главную функцию:

#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;

#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, куда нужно поместить результат чтения. Смещение к кластеру на разделе вычисляется по формуле (см. ):

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; // вычисляем смещение к кластеру

< 0) return -1;

Return 0;

Функция read_directory выполняет чтение записей каталога (не корневого) и помещает результат в область памяти, на которую настроен указатель dir_entry:

int read_directory(__u16 start_cluster)

Int i = 1;

U16 next_cluster;

For(; ;i++) {

Выделяем память для хранения содержимого каталога, считываем содержимое стартового кластера и получаем из таблицы FAT16 значение очередного кластера:

If(!dir_entry) return -1;

< 0) return -1;

Next_cluster = fat16;

Сохраним содержимое каталога в отдельном файле (для контроля):

#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 i = 0;

В глобальном буфере dir_entry находится массив элементов каталога, в котором мы собираемся искать запись файла (или каталога). Для поиска организуем цикл. В теле цикла производим копирование элементов каталога в глобальную структуру dentry и сравниваем значение полей name и ext этой структуры с соответствующими полями структуры struct split_name *sn. Совпадение этих полей означает, что мы нашли в массиве элементов каталога запись искомого файла:

for(; ; i++) {

If(!(memcmp(dentry.name, sn->name, sn->name_len)) &&

!(memcmp(dentry.ext, sn->ext, sn->ext_len)))

Break;

If(!dentry.name) 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.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;

Этот фрагмент можно также реализовать на ассемблере:

" 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 446 0x1BE 16 0x1CE 16 0x1DE 16 0x1EE 16 0x1FE 2

Структура записи элемента таблицы разделов показана в таблице 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; // координаты начала раздела

U8 type_part; // системный идентификатор

U8 end_part; // координаты конца раздела

U32 sect_before; // число секторов перед разделом

U32 sect_total; // размер раздела в секторах (число секторов в разделе)

Элемент первичного раздела указывает сразу на загрузочный сектор логического диска (в первичном разделе всегда имеется только один логический диск), а элемент расширенного раздела – на список логических дисков, составленный из структур, которые именуются вторичными MBR (Secondary MBR, SMBR).

Свой блок SMBR имеется у каждого диска расширенного раздела. SMBR имеет структуру, аналогичную MBR, но загрузочная запись у него отсутствует (заполнена нулями), а из четырех полей описателей разделов используются только два. Первый элемент раздела при этом указывает на логический диск, второй элемент указывает на следующую структуру SMBR в списке. Последний SMBR списка содержит во втором элементе нулевой код раздела.

Вернемся к рассмотрению модуля чтения файла с раздела FAT32.

Заголовочные файлы:

#include

#include

#include

#include

#include

Сигнатура 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))

Установим ограничение на количество логических дисков:

#define MAX_PART 20

Следующий массив структуры будет содержать информацию о логических дисках на устройстве (жестком диске):

struct pt_struct {

U8 bootable;

U8 start_part;

U8 type_part;

U8 end_part;

U32 sect_before;

U32 sect_total;

} pt_t;

int hard; // дескриптор файла устройства

U8 mbr; // сюда считаем MBR

Номер раздела, на котором создана файловая система FAT32:

#define FAT32_PART_NUM 5

Структуры загрузочного сектора, сектора FSInfo и элемента каталога (определены в файле ):

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.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;

Входные данные:

  • hard – дескриптор файла устройства;
  • seek – смещение к расширенному разделу от начала диска (в байтах).

Для получения информации о логических дисках организуем цикл:

For(;;num++) {

Считываем SMBR, находящуюся по смещению seek от начала диска:

Memset((void *)smbr, 0, 512);

Pread64(hard, smbr, 512, seek);

Заполняем два элемента таблицы pt_t, начиная с позиции num. Первый элемент будет указывать на логический диск, а второй – на следующую структуру SMBR:

Memset((void *)&pt_t, 0, PT_SIZE * 2);

Memcpy((void *)&pt_t, smbr + 0x1BE, PT_SIZE * 2);

Вносим поправку в поле «Номер начального сектора» – отсчет ведется от начала диска:

Pt_t.sect_before += (seek / 512);

Если код типа раздела равен нулю, то больше логических дисков нет:

If(!(pt_t.type_part)) break;

Вычисляем смещение к следующему SMBR:

Seek = ((__u64)(pt_t.sect_before + pt_t.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;

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 != "/") 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;

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;

Если каталог занимает один кластер – выходим, если нет – увеличиваем размер памяти и продолжаем чтение:

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;

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) return -1;

Return 0;

На этом рассмотрение модуля чтения файла с раздела FAT32 завершим.

Исходные тексты модуля находятся в каталоге FAT32, файл fat32.c.

Отличия в организации хранения записей о файлах в каталогах для файловых систем FAT и EXT2

Несколько слов об отличиях в организации хранения записей о файлах в каталогах для файловых систем FAT и EXT2. Структура файловой системы EXT2 была рассмотрена в .

C FAT мы только что ознакомились – в ней все элементы каталога имеют фиксированную величину. При создании файла драйвер файловой системы ищет первую незанятую позицию и заполняет её информацией о файле. Если длина каталога не умещается в одном кластере, то под него отводится ещё один кластер и т. д.

Рассмотрим, как обстоят дела в EXT2.

Предположим, у нас есть раздел с файловой системой EXT2, размер блока равен 4096 байт. На этом разделе мы создаем каталог. Размер каталога будет равен размеру блока – 4096 байт. В каталоге операционная система сразу создаёт две записи – запись текущего и запись родительского каталогов. Запись текущего каталога займет 12 байт, в то время как длина записи родительского будет равна 4084 байта. Создадим в этом каталоге какой-нибудь файл. После этого в каталоге будут присутствовать три записи – запись текущего каталога длиной 12 байт, запись родительского каталога длиной уже 12 байт, и запись созданного файла длиной, как вы наверно догадались, 4072 байт. Если мы удалим созданный файл, длина записи родительского каталога опять возрастёт до 4084 байт.

Таким образом, при создании файла драйвер файловой системы EXT2 ищет в каталоге запись максимальной длины и расщепляет её, выделяя место для новой записи. Ну, а если всё-таки места не хватает, под каталог отводится ещё один блок, и длина каталога становится равной 8192 байт.

И в заключение – небольшая правка к статье «Архитектура файловой системы EXT2» .

Эта правка касается функции определения номера 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++) {

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;

Литература:

  1. В.Кулаков. Программирование на аппаратном уровне: специальный справочник. 2-е изд. / – СПб.: Питер, 2003 г. – 848 с.
  2. А.В.Гордеев, А.Ю.Молчанов. Системное программное обеспечение / – СПб.: Питер – 2002 г.
  3. Мешков В. Архитектура файловой системы ext2. – Журнал «Системный администратор», № 11(12), ноябрь 2003 г. – 26-32 с.

Вконтакте

Многие пользователи сталкиваются с непониманием основ работы файловых систем Windows. Казалось бы, зачем ненужная теория? На самом деле именно знание глубокого функционирования различных файловых систем позволяет верно выбирать ту или иную файловую систему для того или иного носителя информации. Порой ошибка в выборе может стать критической позже при решении задачи восстановления информации или преждевременного износа носителя.

Файловая система состоит из системы управления файлами и совокупности файлов на определенном виде носителя (CD, DVD, FDD, HDD, Flash ит.д.). Система управления файлами обеспечивает пользователям и приложениям возможность доступа к файлам, их сохранения и поддержку целостности их содержимого. Наиболее распространенным долговременным носителем информации в современных вычислительных системах является жесткий диск – «Винчестер». Этот термин применяется к любому герметичному диску с аэродинамической конструкцией считывающих магнитных головок.

Файловые системы современных операционных систем устанавливаются в разделы жесткого диска.

FAT 32. Простота и надежность.

Существуют три файловые системы FAT: FAT12 (для гибких дисков FDD), FAT16, FAT32. Они различаются количестом бит (12, 16, 32) для указания номера кластера в системе управления файлами. В файловых системах FAT логическое дисковое пространство любого логического диска делится на системную область и область данных. BR – загрузочная запись Boot Record; RS – зарезервированные сектора; FAT1, FAT2 – таблицы 1 и 2 размещения файлов; RDir (Root directory, ROOT) – корневой каталог. Область данных разбивается на кластеры, которые представляют собой 1 или несколько смежных секторов. В таблице FAT кластеры, принадлежащие одному файлу, связываются по цепочке. Картой области данных является, по сути, Таблица размещения файлов (File Allocation Table - FAT) Каждый элемент таблицы FAT (12, 16 или 32 бит) соответствует одному кластеру диска и характеризует его состояние: свободен, занят или является сбойным кластером (bad clаster). Для указания номера кластера в системе управления файлами FAT16 используется 16-ти битовое слово, и можно адресовать 65536 кластеров.

Кластер – это минимально адресуемая единица дисковой памяти, выделяемая для файла. Файл или каталог занимает целое число кластеров. Разбиение области данных на кластеры вместо использования секторов позволяет: уменьшить размер таблицы FAT, уменьшить фрагментацию файлов, сокращается длина цепочек файла, ускоряется доступ к файлу. Последний кластер может быть задействован не полностью, что приведет к заметной потере дискового пространства при большом размере кластера. На дискете кластер занимает 1 или 2 сектора. На жестком диске – 4, 8, 16, 32, 64 – сектора в одном кластере. Каждый элемент имеет следующую структуру: имя файла, атрибут файла, резервное поле, время создания, дата создания, дата последнего доступа, резерв, дата последней модификации, время последней модификации, номер начального кластера Fat, размер файла.

В данном примере файл с именем MyFile.txt размещается, начиная с 8-го кластера и занимает 12 кластеров. Цепочка кластеров для данного случая: 8,9,А,В,15,16,17,19,1А,1В,1C,1D. Кластер с номером 18 помечен кодом F7 как плохой. Он не может быть использован для размещения данных. Этот код выставляется утилитами форматирования и проверки дисков. Кластер 1D помечен кодом FF как конечный, принадлежащий данному файлу. Свободные кластеры помечены кодом 0. При выделении нового кластера для записи в файл берется 1-ый свободный кластер. Поскольку файлы на диске изменяются, удаляются, перемещаются, увеличиваются и уменьшаются, то данное правило размещения приводит к фрагментации, т.е. данные одного файла располагаются не в смежных кластерах, а порой очень удаленных друг от друга. Образовывается сложная цепочка. Это приводит к замедлению работы с файлами. Так как Fat используется при доступе к диску очень интенсивно, она загружается в оперативную память. Система Fat32 намного эффективнее расходует дисковое пространство, так как использует кластеры меньшего размера по сравнению с предыдущими версиями Fat. По сравнению с Fat16 это дает экономию 10-16%.

Элемент каталога в поле атрибут может хранить следующие значения:

1) архивный (устанавливается при изменении файла и снимается программой выполняющей резервное копирование файлов на другой носитель);

2) директория;

3) метка тома;

4) системный;

5) скрытый;

6) только для чтения.

Длинные имена в FAT32 обеспечиваются использованием нескольких элементов записи каталога: для одного файла (один элемент – одна запись для имени 8.3, и 24 записи для самого длинного имени, которое может содержать до 256 символов. Поэтому не рекомендуется использовать длинные имена.

Основной недостаток FAT - медленная работа с файлами. При создании файла работает правило - выделяется первый свободный кластер. Это ведет к фрагментации диска и сложным цепочкам файлов. Отсюда следует замедление работы с файлами.

В принципе, файловая система FAT - это то, что нужно сегодня избегать. Поэтому жизненно важно выбрать подходящий, который позволит вам избежать это файловой системы.

NTFS: удобство и высокая скорость.

Одним из основных понятий, используемых при работе с NTFS, является понятие тома. Возможно создание отказоустойчивого тома, занимающего несколько разделов, то есть использование RAID-технологии. NTFS делит все полезное дисковое пространство тома на кластеры - блоки данных, адресуемые как единицы данных. NTFS поддерживает размеры кластеров от 512 байт до 64 Кбайт; 2 или 4 Кбайт диска отводятся под MFT-зону - пространство, которое может занимать, увеличиваясь в размере, главный служебный метафайл MFT. Запись данных в эту область невозможна. MFT-зона пуста, чтобы служебный файл (MFT) по возможности не фрагментировался при своем росте.

MFT (общая таблица файлов) - централизованный каталог всех остальных файлов диска, в том числе и себя самого. MFT поделен на записи фиксированного размера в 1 Кбайт, каждая запись соответствует какому-либо файлу. Первые 16 файлов носят служебный характер и недоступны операционной системе - они называются метафайлами, причем самый первый метафайл - сам MFT. Эти первые 16 элементов MFT - единственная часть диска, имеющая строго фиксированное положение. Копия этих же 16 записей хранится в середине тома для надежности, поскольку они очень важны. Остальные части MFT-файла могут располагаться в произвольных местах диска - восстановить его положение можно с помощью его самого, «зацепившись» за самую основу - за первый элемент MFT. Каждый файл в NTFS представлен с помощью потоков, у него нет данных, а есть «потоки». Один из потоков - данные файла. Для одного файла можно определить несколько потоков данных.

Основные особенности NTFS:

Работа на дисках большого объема происходит эффективно (намного эффективнее, чем в FAT);

Имеются средства для ограничения доступа к файлам и каталогам;

Разделы NTFS обеспечивают локальную безопасность как файлов, так и каталогов;

Введен механизм транзакций, при котором осуществляется журналирование файловых операций;

Существенное увеличение надежности;

Сняты многие ограничения на максимальное количество дисковых секторов и/или кластеров;

Имя файла в NTFS, в отличие от файловых систем FAT и HPFS, может содержать любые символы, включая полный набор национальных алфавитов, так как данные представлены в Unicode - 16-битном представлении, которое дает 65535 разных символов. Максимальная длина имени файла в NTFS - 255 символов.

Система NTFS также обладает встроенными средствами сжатия, которые можно применять к отдельным файлам, целым каталогам и даже томам (и впоследствии отменять или назначать их по своему усмотрению). Каталог в NTFS представляет собой специальный файл, хранящий ссылки на другие файлы и каталоги.

NTFS обеспечивает безопасность на уровне файлов; это означает, что права доступа к томам, каталогам и файлам могут зависеть от учетной записи пользователя и тех групп, к которым он принадлежит. Каждый раз, когда пользователь обращается к объекту файловой системы, его права доступа проверяются по списку разрешений данного объекта. Если пользователь обладает достаточным уровнем прав, его запрос удовлетворяется; в противном случае запрос отклоняется. Эта модель безопасности применяется как при локальной регистрации пользователей на компьютерах с NT, так и при удаленных сетевых запросах.

Система NTFS также обладает определенными средствами самовосстановления. NTFS поддерживает различные механизмы проверки целостности системы, включая ведение журналов транзакций, позволяющих воспроизвести файловые операции записи по специальному системному журналу.

Основной недостаток файловой системы NTFS - служебные данные занимают много места (например, каждый элемент каталога занимает 2 Кбайт) - для малых разделов служебные данные могут занимать до 25% объема носителя.

Таким образом, выбирая тип файловой системы, мы выбираем не какое-то абстрактное действие, мы принимаем комплекс решений, которые влияют на всю систему в целом. Зачем же знать так подробно всю подноготную файловой системы? Это необходимо для ее возможного восстановления, о чем мы расскажем в одной из следующих статей=)

Введение

2.1 Система FAT16

2.2 Система FAT32

2.3 Сравнение FAT16 и FAT32

3.1 Система NTFS

3.2 Сравнение NTFS и FAT32

Заключение

Список литературы

Введение

В настоящее время на одном диске в среднем записывается несколько десятков тысяч файлов. Как разобраться во всем этом многообразии с тем, чтобы точно адресоваться к файлу? Назначение файловой системы - эффективное решение, указанной задачи.

Файловая система с точки зрения пользователя - это "пространство", в котором размещаются файлы. А как научный термин - это способ хранения и организации доступа к данным на информационном носителе или его разделе. Наличие файловой системы позволяет определить, как называется файл, где он находится. Поскольку на IBM PC - совместимых компьютерах информация храниться в основном на дисках, то применяемые на них файловые системы определяют организацию данных именно на дисках (точнее, на логических дисках). Мы рассмотрим файловую систему FAT.

файловая система fat ntfs

1. История создания и общая характеристика файловой системы FAT

Файловая система FAT (File Allocation Table) была разработана Биллом Гейтсом и Марком МакДональдом в 1977 году и первоначально использовалась в операционной системе 86-DOS. Чтобы добиться переносимости программ из операционной системы CP/M в 86-DOS, в ней были сохранены ранее принятые ограничения на имена файлов. В дальнейшем 86-DOS была приобретена Microsoft и стала основой для ОС MS-DOS 1.0, выпущенной в августе 1981 года. FAT была предназначена для работы с гибкими дисками размером менее 1 Мбайта, и вначале не предусматривала поддержки жестких дисков. В настоящее время FAT поддерживает файлы и разделы размеров до 2 Гбайт.

В FAT применяются следующие соглашения по именам файлов:

имя должно начинаться с буквы или цифры и может содержать любой символ ASCII, за исключением пробела и символов "/\ :; |=,^*?

длина имени не превышает 8 символов, за ним следует точка и необязательное расширение длиной до 3 символов.

регистр символов в именах файлов не различается и не сохраняется.

Структура раздела FAT изображена на табл 1.1 В блоке параметров BIOS содержится необходимая BIOS информация о физических характеристиках жесткого диска. Файловая система FAT не может контролировать отдельно каждый сектор, поэтому она объединяет смежные сектора в кластеры (clusters). Таким образом, уменьшается общее количество единиц хранения, за которыми должна следить файловая система. Размер кластера в FAT является степенью двойки и определяется размером тома при форматировании диска (табл.1.2). Кластер представляет собой минимальное пространство, которое может занимать файл. Это приводит к тому, что часть пространства диска расходуется впустую. В состав операционной системы входят различные утилиты (DoubleSpace, DriveSpace), предназначенные для уплотнения данных на диске.

Табл. 1.1 - Структура раздела FAT

Загрузочный сектор Блок параметров BIOS (BPB) FATFAT (копия) Корневой каталогОбласть файлов

Свое название FAT получила от одноименной таблицы размещения файлов. В таблице размещения файлов хранится информация о кластерах логического диска. Каждому кластеру в FAT соответствует отдельная запись, которая показывает, свободен ли он, занят ли данными файла, или помечен как сбойный (испорченный). Если кластер занят под файл, то в соответствующей записи в таблице размещения файлов указывается адрес кластера, содержащего следующую часть файла. Из-за этого FAT называют файловой системой со связанными списками. Оригинальная версия FAT, разработанная для DOS 1.00, использовала 12-битную таблицу размещения файлов и поддерживала разделы объемом до 16 Мб (в DOS можно создать не более двух разделов FAT). Для поддержки жестких дисков размером более 32 Мб разрядность FAT была увеличена до 16 бит, а размер кластера - до 64 секторов (32 Кб). Так как каждому кластеру может быть присвоен уникальный 16-разрядный номер, то FAT поддерживает максимально 216, или 65536 кластеров на одном томе.

Табл.1.2 - Размеры кластера

Размер разделаРазмер кластераТип FAT< 16 Мб4 КбFAT1216 Мб - 127 Мб2 КбFAT16128 Мб - 255 Мб4 КбFAT16256 Мб - 511 Мб8 КбFAT16512 Мб - 1023 Мб16 КбFAT161 Гб - 2 Гб32 КбFAT16

Поскольку загрузочная запись слишком мала для хранения алгоритма поиска системных файлов на диске, то системные файлы должны находиться в определенном месте, чтобы загрузочная запись могла их найти. Фиксированное положение системных файлов в начале области данных накладывает жесткое ограничение на размеры корневого каталога и таблицы размещения файлов. Вследствие этого общее число файлов и подкаталогов в корневом каталоге на диске FAT ограничено 512.

Каждому файлу и подкаталогу в FAT соответствует 32-байтный элемент каталога, содержащий имя файла, его атрибуты (архивный, скрытый, системный и "только для чтения), дату и время создания (или внесения в него последних изменений), а также прочую информацию (табл.1.3).

Табл.1.3 - Элементы каталога

Файловая система FAT всегда заполняет свободное место на диске последовательно от начала к концу. При создании нового файла или увеличении уже существующего она ищет самый первый свободный кластер в таблице размещения файлов. Если в процессе работы одни файлы были удалены, а другие изменились в размере, то появляющиеся в результате пустые кластеры будут рассеяны по диску. Если кластеры, содержащие данные файла, расположены не подряд, то файл оказывается фрагментированным. Сильно фрагментированные файлы значительно снижают эффективность работы, так как головки чтения/записи при поиске очередной записи файла должны будут перемещаться от одной области диска к другой. В состав операционных систем, поддерживающих FAT, обычно входят специальные утилиты дефрагментации диска, предназначенные повысить производительность файловых операций.

Еще один недостаток FAT заключается в том, что ее производительность сильно зависит от количества файлов, хранящихся в одном каталоге. При большом количестве файлов (около тысячи), выполнение операции считывания списка файлов в каталоге может занять несколько минут. Это обусловлено тем, что в FAT каталог имеет линейную неупорядоченную структуру, и имена файлов в каталогах идут в порядке их создания. В результате, чем больше в каталоге записей, тем медленнее работают программы, так как при поиске файла требуется просмотреть последовательно все записи в каталоге. Поскольку FAT изначально проектировалась для однопользовательской операционной системы DOS, то она не предусматривает хранения такой информации, как сведения о владельце или полномочия доступа к файлу/каталогу.является наиболее распространенной файловой системой и ее в той или иной степени поддерживают большинство современных ОС. Благодаря своей универсальности FAT может применяться на томах, с которыми работают разные операционные системы.

Хотя нет никаких препятствий использовать при форматировании дискет любую другую файловую систему, большинство ОС для совместимости используют FAT. Отчасти это можно объяснить тем, что простая структура FAT требует меньше места для хранения служебных данных, чем остальные системы. Преимущества других файловых систем становятся заметны только при использовании их на носителях объемом более 100 Мб.

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

2. Характеристика файловых систем FAT16 и FAT32 и их сравнение

.1 Система FAT16

Файловая система FAT 16, являющаяся основной для операционных систем DOS, Windows 95⁄98⁄Me, Windows NT⁄2000⁄XP, а также поддерживается большинством других систем. FAT 16 представляет собой простую файловую систему, разработанную для небольших дисков и простых структур каталогов. Название происходит от названия метода организации файлов - Таблица размещения файлов (File Allocation Table). Эта таблица размещается в начале диска. Число 16 означает, что данная файловая система 16-разрядная - для адресации кластеров используется 16 разрядов. Операционная система использует Таблицу размещения файлов для поиска файла и определения кластеров, которые этот файл занимает на жестком диске. Кроме того, в Таблице фиксируются сведения о свободных и дефектных кластерах. Чтобы легче было осмыслить файловую систему FAT16 представьте себе оглавление книги и как вы работаете с этим оглавлением, вот именно также операционная система работает с FAT 16.

Чтобы прочитать файл, операционная система должна найти по имени файла запись в папке и прочитать номер первого кластера файла. Первый кластер представляет собой начало файла. Затем необходимо прочитать соответствующий первому кластеру файла элемент FAT. Если элемент содержит метку - последний в цепочке, то дальше ни чего искать не нужно: весь файл умещается в одном кластере. Если кластер не последний, то элемент таблицы содержит номер следующего кластера. Содержимое следующего кластера должно быть прочитано вслед за первым. Когда будет найден последний кластер в цепочке, то, если файл не занимает весь кластер целиком, необходимо отсечь лишние байты кластера. Лишние байты отсекаются по длине файла, хранящейся в записи папки.

Чтобы записать файл, операционная система должна выполнить следующую последовательность действий. В свободном элементе папки создается описание файла, затем ищется свободный элемент FAT, и ссылка на него размещается в записи папки. Занимается первый кластер, описываемый найденным элементом FAT. В этот элемент FAT помещается номер следующего кластера или признак последнего кластера в цепочке.

Операционная система действует таким образом, чтобы собирать цепочки из соседних кластеров по нарастанию номера. Понятно, что обращение к последовательно расположенным кластерам будет происходить значительно быстрее, чем к кластерам, случайным образом разбросанным по диску. При этом игнорируются уже занятые и помеченные в FAT как дефектные кластеры.

В файловой системе FAT16 под номер кластера отведено 16 разрядов. Поэтому максимальное количество кластеров составляет 65525, а максимальный размер кластера 128 секторов. В таком случае максимальный размер разделов или дисков в FAT16 составляет 4,2 гигабайта. При логическом форматировании диска или раздела операционная система старается использовать минимальный размер кластера, при котором получающееся количество кластеров не превышает 65525. Очевидно, что чем больше размер раздела, тем больше должен быть размер кластера. Многие операционные системы неправильно работают с кластером размером в 128 секторов. В результате максимальный размер раздела FAT16 уменьшается до 2 гигабайт. Обычно, чем больше размер кластера, тем больше становятся потери дискового пространства. Это связано с тем, что последний кластер, занимаемый файлом, заполнен лишь частично. Например, если файл размером 17 Кбайт записывается в раздел с размером кластера 16 Кбайт, то этот файл займет два кластера, причем первый кластер будет заполнен полностью, а во втором кластере будет записан только 1 Кбайт данных, а остальные 15 Кбайт пространства второго кластера останутся не заполненными и будут недоступными для записи других файлов. Если на больших дисках записывается большое количество маленьких файлов, то потери дискового пространства будут значительны. В следующей таблице 2.1 приводятся сведения о возможных потерях дискового пространства при разных размерах раздела.

Табл. 2.1.1 - Потери дискового пространства

Размер разделаРазмер кластераПотери дискового пространства127 Мб2 Кб2%128-255 Мб4 Кб4%256-511 МБ8 Кб10%512-1023 МБ16 Кб25%1024-2047 МБ32 Кб40%2048-4096 Мб64 Кб50%

Возможны два способа уменьшения потерь дискового пространства. Первый - разбиение дискового пространства на мелкие разделы с малым размером кластера. Второй - использование файловой системы FAT32 <#"center">2.2 Система FAT32

Файловая система FAT32 - более новая файловая система на основе формата FAT, она поддерживается Windows 95 OSR2, Windows 98 и Windows Millennium Edition. FAT32 использует 32-разрядные идентификаторы кластеров, но при этом резервирует старшие 4 бита, так что эффективный размер идентификатора кластера составляет 28 бит. Поскольку максимальный размер кластеров FAT32 равен 32 Кбайт, теоретически FAT32 может работать с 8-терабайтными томами. Windows 2000 ограничивает размер новых томов FAT32 до 32 Гбайт, хотя поддерживает существующие тома FАТ32 большего размера (созданные в других операционных системах). Большее число кластеров, поддерживаемое FAT32, позволяет ей управлять дисками более эффективно, чем FAT 16. FAT32 может использовать 512-байтовые кластеры для томов размером до 128 Мбайт.

Файловая система FAT 32 в Windows 98 используется в качестве основной. С этой операционной системой поставляется специальная программа преобразования диска из FAT 16 в FAT 32. Windows NT и Windows 2000 тоже могут использовать файловую систему FAT, и поэтому можно загрузить компьютер с DOS-диска и иметь полный доступ ко всем файлам. Однако некоторые из самых прогрессивных возможностей Windows NT и Windows 2000 обеспечиваются ее собственной файловой системой NTFS (NT File System). NTFS позволяет создавать на диске разделы объемом до 2 Тбайт (как и FAT 32), но, кроме этого, в нее встроены функции сжатия файлов, безопасности и аудита, необходимые при работе в сетевой среде. А в Windows 2000 реализуется поддержка файловой системы FAT 32. Установка операционной системы Windows NT начинается на диске FAT, но по желанию пользователя в конце установки данные на диске могут быть конвертированы в формат NTFS.

Можно сделать это и позже, воспользовавшись утилитой Convert. exe, поставляемой вместе с операционной системой. Преобразованный к системе NTFS раздел диска становится недоступным для других операционных систем. Чтобы вернуться в DOS, Windows 3.1 или Windows 9x, нужно удалить раздел NTFS, а вместо него создать раздел FAT. Windows 2000 можно устанавливать на диск с файловой системой FAT 32 и NTFS.

Возможности файловых систем FАТ32 гораздо шире возможностей FAT16. Самая важная ее особенность в том, что она поддерживает диски объемом до 2 047 Гбайт и работает с кластерами меньшего размера, благодаря чему существенно сокращает объемы неиспользуемого дискового пространства. Например, жесткий диск объемом 2 Гбайт в FAT16 использует кластеры размером по 32 Кбайт, а в FAT32 - кластеры размером по 4 Кбайт. Чтобы по возможности сохранить совместимость с существующими программами, сетями и драйверами устройств, FAT32 реализована с минимальными изменениями в архитектуре, API-интерфейсах, структурах внутренних данных и дисковом формате. Но, так как размер элементов таблицы FAT32 теперь составляет четыре байта, многие внутренние и дисковые структуры данных, а также API-интерфейсы пришлось пересмотреть или расширить. Отдельные API на FАТ32-дисках блокируются, чтобы унаследованные дисковые утилиты не повредили содержимое FAT32-дисков. На большинстве программ эти изменения никак не скажутся. Существующие инструментальные средства и драйверы будут работать и на FAT32-дисках. Однако драйверы блочных устройств MS-DOS (например, Aspidisk. sys) и дисковые утилиты нуждаются в модификации для поддержки FAT32. Все дисковые утилиты, поставляемые Microsoft (Format, Fdisk, Defrag, а также ScanDisk для реального и защищенного режимов), переработаны и полностью поддерживают FAT32. Кроме того, Microsoft помогает ведущим поставщикам дисковых утилит и драйверов устройств в модификации их продуктов для поддержки FAT32. FAT32 эффективнее FAT16 при работе с дисками большего объема и не требует их разбиения на разделы по 2 Гбайт. Windows 98 обязательно поддерживает FAT16, так как именно эта файловая система совместима с другими операционными системами, в том числе сторонних компании. В MS-DOS реального режима и в безопасном режиме Windows 98, файловая система FAT32 работает значительно медленнее, чем FAT16. Поэтому, при запуске программ в режиме MS DOS желательно включить в файл Autoexec. bat или PIF-файл команду для загрузки Smartdrv. exe, что ускорит дисковые операции. Некоторые устаревшие программы, рассчитанные на спецификацию FAT16, могут сообщать неправильную информацию об объеме свободного или общего дискового пространства, если он больше 2 Гбайт. Windows 98 предоставляет новые API-интерфейсы для MS-DOS и Win32, которые позволяют корректно определять эти показатели.

.3 Сравнение FAT16 и FAT32

Табл.2.3.1 - Сравнение файловых систем FAT16 и FAT32

FAT16FAT32Реализована и используется большинством операционных систем (MS-DOS, Windows 98, Windows NT, OS/2, UNIX). На данный момент поддерживается только в Windows 95 OSR2 и Windows 98. Очень эффективна для логических дисков размером менее 256 Мбайт. Не работает с дисками объемом менее 512 Мбайт. Поддерживает сжатие дисков, например по алгоритму DriveSpace. Не поддерживает сжатие дисков. Обрабатывает максимум 65 525 кластеров, размер которых зависит от объема логического диска. Так как максимальный размер кластеров равен 32 Кбайт, FAT16 может работать с логическими дисками объемом не более 2 Гбайт. Способна работать с логическими дисками объемом до 2 047 Гбайт при максимальном размере кластеров в 32 Кбайт.

Максимально возможная длина файла в FAT32 равна 4 Гбайт за вычетом 2 байтов. Win32-приложения могут открывать файлы такой длины без специальной обработки. Остальные приложения должны использовать прерывание Int 21h, функцию 716С (FAT32) с флагом открытия, равным EXTEND-SIZE (1000h).

В файловой системе FAT32 на каждый кластер в таблице размещения файлов отводится по 4 байта, тогда как в FAT16 - по 2, а в FАТ12 - по 1,5.

Старшие 4 бита 32-разрядного элемента таблицы FAT32 зарезервированы и не участвуют в формировании номера кластера. Программы, напрямую считывающие FАТ32-таблицу, должны маскировать эти биты и предохранять их от изменения при записи новых значений.

Итак, FAT32 обладает следующими преимуществами в сравнении с прежними реализациями файловой системы FAT:

поддерживает диски объемом до 2 Тбайт;

эффективнее организует дисковое пространство. FAT32 использует кластеры меньшего размера (4 Кбайт для дисков объемом до 8 Гбайт), что позволяет сэкономить до 10-15% пространства на больших дисках по сравнению с FAT;

корневой каталог FAT 32, как и все остальные каталоги, теперь не ограничен, он состоит из цепочки кластеров и может быть расположен в любом месте диска;

имеет более высокую надежность: FAT32 способна перемещать корневой каталог и работать с резервной копией FAT, кроме того, загрузочная запись на FАТ32-дисках расширена и теперь включает резервную копию критически важных структур данных, а это означает, что FАТ32-диски менее чувствительны к возникновению отдельных сбойных участков, чем существующие FAT-тома;

программы загружаются на 50% быстрее.

Табл.2.3.2 - Сравнение размеров кластеров

Объем дискаРазмер кластеров в FAT16, КбайтРазмер кластеров в FAT32, Кбайт256 Мбайт-511 Мбайт8Не поддерживается512 Мбайт - 1023 Мбайт1641024 Мбайт - 2 Гбайт3242 Гбайт - 8 ГбайтНе поддерживается48 Гбайт-16 ГбайтНе поддерживается816 Гбайт-32 ГбайтНе поддерживается16Более 32 ГбайтНе поддерживается32

3. Альтернативная файловая система NTFS и её сравнение с FAT32

3.1 Система NTFS

(New Technology File System) - наиболее предпочтительная файловая система при работе с ОС Windows NT, поскольку она была специально разработана для данной системы. В состав Windows NT входит утилита convert, осуществляющая конвертирование томов с FAT и HPFS в тома NTFS. В NTFS значительно расширены возможности по управлению доступом к отдельным файлам и каталогам, введено большое число атрибутов, реализована отказоустойчивость, средства динамического сжатия файлов, поддержка требований стандарта POSIX. NTFS позволяет использовать имена файлов длиной до 255 символов, при этом она использует тот же алгоритм для генерации короткого имени, что и VFAT. NTFS обладает возможностью самостоятельного восстановления в случае сбоя ОС или оборудования, так что дисковый том остается доступным, а структура каталогов не нарушается.

Каждый файл на томе NTFS представлен записью в специальном файле - главной файловой таблице MFT (Master File Table). NTFS резервирует первые 16 записей таблицы размером около 1 Мб для специальной информации. Первая запись таблицы описывает непосредственно саму главную файловую таблицу. За ней следует зеркальная запись MFT. Если первая запись MFT разрушена, NTFS считывает вторую запись, чтобы отыскать зеркальный файл MFT, первая запись которого идентична первой записи MFT. Местоположение сегментов данных MFT и зеркального файла MFT хранится в секторе начальной загрузки. Копия сектора начальной загрузки находится в логическом центре диска. Третья запись MFT содержит файл регистрации, применяемый для восстановления файлов. Семнадцатая и последующие записи главной файловой таблицы используются собственно файлами и каталогами на томе.

В журнале транзакций (log file) регистрируются все операции, влияющие на структуру тома, включая создание файла и любые команды, изменяющие структуру каталогов. Журнал транзакций применяется для восстановления тома NTFS после сбоя системы. Запись для корневого каталога содержит список файлов и каталогов, хранящихся в корневом каталоге.

Схема распределения пространства на томе хранится в файле битовой карты (bitmap file). Атрибут данных этого файла содержит битовую карту, каждый бит которой представляет один кластер тома и указывает, свободен ли данный кластер или занят некоторым файлом.также поддерживает файл плохих кластеров (bad cluster file) для регистрации поврежденных участков на томе и файл тома (volume file), содержащий имя тома, версию NTFS и бит, который устанавливается при повреждении тома. Наконец, имеется файл, содержащий таблицу определения атрибутов (attribute definition table), которая задает типы атрибутов, поддерживаемые на томе, и указывает можно ли их индексировать, восстанавливать операцией восстановления системы и т.д.распределяет пространство кластерами и использует для их нумерации 64 разряда, что дает возможность иметь 264 кластеров, каждый размером до 64 Кбайт. Как и в FAT размер кластера может меняться, но необязательно возрастает пропорционально размеру диска. Размеры кластеров, устанавливаемые по умолчанию при форматировании раздела, приведены в табл.3.1.

Размер разделаРазмер кластера< 512 Мб512 байт513 Мб - 1024 Мб (1 Гб) 1 Кб1 Гб - 2 Гб2 Кб2 Гб - 4 Гб4 Кб4 Гб - 8 Гб8 Кб8 Гб - 16 Гб16 Кб16 Гб - 32 Гб32 Кб> 32 Гб64 Кбпозволяет хранить файлы размером до 16 эксабайт (264 байт) и располагает встроенным средством уплотнения файлов в реальном времени. Сжатие является одним из атрибутов файла или каталога и подобно любому атрибуту может быть снято или установлено в любой момент (сжатие возможно на разделах с размером кластера не более 4 Кб). При уплотнении файла, в отличие от схем уплотнения используемых в FAT, применяется пофайловое уплотнение, таким образом, порча небольшого участка диска не приводит к потере информации в других файлах.

Для уменьшения фрагментации NTFS всегда пытается сохранить файлы в непрерывных блоках. Эта система использует структуру каталогов в виде B-дерева, аналогичную высокопроизводительной файловой системе HPFS, а не структуре со связанным списком применяемой в FAT. Благодаря этому поиск файлов в каталоге осуществляется быстрее, поскольку имена файлов хранятся сортированными в лексикографическом порядке.была разработана как восстанавливаемая файловая система, использующая модель обработки транзакций. Каждая операция ввода-вывода, изменяющая файл на томе NTFS, рассматривается системой как транзакция и может выполняться как неделимый блок. При модификации файла пользователем сервис файла регистрации фиксирует всю информацию необходимую для повторения или отката транзакции. Если транзакция завершена успешно, производится модификация файла. Если нет, NTFS производит откат транзакции.

Несмотря на наличие защиты от несанкционированного доступа к данным NTFS не обеспечивает необходимую конфиденциальность хранимой информации. Для получения доступа к файлам достаточно загрузить компьютер в DOS с дискеты и воспользоваться каким-нибудь сторонним драйвером NTFS для этой системы.

Начиная с версии Windows NT 5.0 (новое название Windows 2000) Microsoft поддерживает новую файловую систему NTFS 5.0. В новой версии NTFS были введены дополнительные атрибуты файлов; наряду с правом доступа введено понятие запрета доступа, позволяющее, например, при наследовании пользователем прав группы на какой-нибудь файл, запретить ему возможность изменять его содержимое. Новая система также позволяет:

вводить ограничения (квоты) на размер дискового пространства, предоставленного пользователям;

проецировать любой каталог (как на локальном, так и на удаленном компьютере) в подкаталог на локальном диске.

Интересной возможностью новой версии Windows NT является динамическое шифрование файлов и каталогов, повышающее надежность хранения информации. В состав Windows NT 5.0 входит файловая система с шифрованием (Encrypting File System, EFS), использующая алгоритмы шифрования с общим ключом. Если для файла установлен атрибут шифрования, то при обращении пользовательской программы к файлу для записи или чтения происходит прозрачное для программы кодирование и декодирование файла.

.2 Сравнение NTFS и FAT32

Достоинства:

Быстрая скорость доступа к файлам малого размера;

Размер дискового пространства на сегодняшний день практически не ограничен;

Фрагментация файлов не влияет на саму файловую систему;

Высокая надежность сохранения данных и собственно самой файловой структуры;

Высокая производительность при работе с файлами большого размера;

Недостатки:

Более высокие требования к объему оперативной памяти по сравнению с FAT 32;

Работа с каталогами средних размеров затруднена из-за их фрагментации;

Более низкая скорость работы по сравнению с FAT 3232

Достоинства:

Высокая скорость работы;

Низкое требование к объему оперативной памяти;

Эффективная работа с файлами средних и малых размеров;

Более низкий износ дисков, вследствие меньшего количества передвижений головок чтения/записи.

Недостатки:

Низкая защита от сбоев системы;

Не эффективная работа с файлами больших размеров;

Ограничение по максимальному объему раздела и файла;

Снижение быстродействия при фрагментации;

Снижение быстродействия при работе с каталогами, содержащими большое количество файлов;

Итак, обе файловые системы хранят данные в кластерах минимальный размер которого равен 512 b. Как правило обычный размер кластера равен 4 Kb. На этом сходства пожалуй и заканчиваются. Кое-что о фрагментации: скорость работы NTFS резко снижается при заполнении диска на 80 - 90 %. Это связано с фрагментацией служебных и рабочих файлов. Чем больше Вы работаете с таким загруженным диском, тем сильнее фрагментация и тем ниже производительность. В FAT 32 фрагментация рабочей области диска происходит и на более ранних этапах. Дело тут зависит от того, насколько часто Вы записываете/стираете данные. Как и в NTFS, фрагментация сильно снижает производительность. Теперь об оперативной памяти. Объем самой электронной таблицы FAT 32 может занимать в ОЗУ порядка нескольких мегабайт. Но на помощь приходит кэширование. Что записывается в кэш:

Наиболее используемые каталоги;

Данные о всех используемых в данный момент времени файлах;

Данные о свободном пространстве диска;

А что же NTFS? Кэшированию трудно поддаются каталоги больших размеров, а они могут достигать размеров нескольких десятков мегабайт. Плюс MFT, плюс информация о свободном месте на диске. Хотя надо заметить, что NTFS все же довольно экономно расходует ресурсы оперативной памяти. В наличии удачная система хранения данных, в MFT каждая запись примерно равна 1 Kb. Но все же требования к объему ОЗУ выше, чем для FAT 32. Короче, если Ваша память меньше или равна 64 Mb, то эффективнее с точки зрения скорости окажется FAT 32. Если больше - разница в скорости будет маленькая, а зачастую вообще никакой. Теперь о самом жестком диске. Для использования NTFS желательно наличие Bus Mastering. Что это? Это особый режим работы драйвера и контроллера. При использовании BM обмен происходит без участия процессора. Отсутствие ВМ скажется на производительности системы. Кроме этого, вследствие использования более сложной файловой системы количество движений головок чтения/записи возрастает, что так же влияет на скорость. Наличие дискового кэша одинаково положительно сказывается, как на NTFS, так и на FAT 32.

Заключение

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

Область применения FAT32 на самом деле гораздо уже - эту файловую систему стоит применять, если Вы собираетесь получать доступ к разделам и с помощью Windows 9x и с помощью Windows 2000/XP. Но так как актуальность Windows 9x сегодня практически сошла на нет, то и использование этой файловой системы не представляет особого интереса.

Список литературы

1. http://yura. puslapiai. lt/archiv/per/fat.html

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

Возможно вы думаете: «что файловая система это сложная и непонятная штука, ведь с ней работают операционные системы, а там все просто быть не может…»

Частично вы правы, но весь изюм находиться в драйвере файловой системе, т.е. в программе, которая предоставляет API для остальных прикладных программ. Она как раз и выполняет такие действия как:

  • создать файл
  • удалить файл
  • переименовать
  • скопировать
  • показать содержимое каталога
  • перейти в другой каталог и т.п.

Сам принцип организации файловой системы прост.

В этом посте, я не буду рассматривать как устроен драйвер и как он создает/удаляет файлы, я расскажу вам о принципе организации файловой системы FAT16.

(про то, как написать драйвер, есть отдельный )

Почему FAT16?

Я считаю её наиболее удобной для обучения, её легко осмыслить. А зная идею, уже не сложно изучать другие файловые системы — FAT32, NTFS, и т.п.

Зачем мне нужно знать как устроена файловая система?

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

Описание файловой системы FAT16

Для удобного ориентирования по посту, я приведу список вопросов, на которые вы найдете ответы:

Файловая система FAT16 делит все адресное пространство носителя на две области:

  • системную область
  • область данных

Для наглядности изобразим все адресное пространство прямоугольником. Малая верхняя часть прямоугольника (адресного пространства) это системная область, нижняя массивная это область данных.

Все данные, которые мы храним на своем носителе, т.е. все файлы и каталоги — хранятся в области данных. Системная же область, хранит параметры данного носителя и характеристики файлов и директорий – имя файла, имя директориии, атрибуты файла и т.п.

Начнем с простого, пару слов про область данных и как там хранятся данные

Про область данных …

Чтобы не адресовать каждый байт (хотя некоторые носители информации позволяют работать и побайтно) в файловой системе используют другую минимальную адресуемую единицу – сектор . Размер сектора 512 байт . Помимо сектора файловая система FAT16 использует еще такое понятие как кластер . Кластер это один или несколько расположенных подряд секторов .

Этим параметром (число секторов на кластере) часто манипулируют при форматирование носителей информации. Т.к. от него зависит скорость работы и «степень упаковка данных». FAT16 как и все файловые системы использует такое понятие как файл. Файл это область данных имеющая имя и некоторые атрибуты. Физически в области данных это один или несколько занятых кластеров, причем файл занимает целое число кластеров. Даже, если он занимает чуть больше чем два кластера для файловой системы занятых под файл будет считаться три кластера. Поэтому, чем меньше размер кластера, тем больше «степень упаковки данных» и экономичнее используется область данных. С другой стороны, считывать файл из больших кусков памяти т.е. кластеров быстрее, чем из мелких. Поэтому, выбор размера кластера это дело компромисса.

Файловая система FAT16 накладывает ограничения на размер кластера , не более 128 секторов (т.е. не более 64 кб) и на количество кластеров не более 65525 штук . Если использовать все по максимум, т.е. максимальные размер секторов и максимальное количество кластером, то выходит что FAT16 не может адресовать больше чем 4.2 гигабайта информации .

Если мы производим форматирование в автоматическом режиме (когда не указываем размер кластера), то размер кластер выбирается минимальным, при котором получающееся количество кластеров не превышает 65525.

Про системную область …

Системная область создается при форматирование носителя и носит описательный характер . Она состоит из следующих частей:

Разберем каждую часть подробнее

1. Загрузочный сектор

Загрузочный сектор представляет собой таблицу параметров и программу загрузчик . Размер загрузочного сектора обычно 512 байт , но он может быть больше.

Рассмотрим структуру загрузочного сектора.

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

Если посмотреть HEX код , какого-нибудь носителя информации отформатированного в формате FAT16 , то мы увидим значение полей. В качестве примера я приведу HEX код образа в формате FAT16 созданного в WinImage. Для удобства ориентирования по коду, я пометил цветами какой фрагмент HEX кода к какому параметру относиться.

P.S. Значение для каждой ячейки считаются справа налево , например если написано 00 02 h, то на самом деле это 02 00 h, т.е. 512

P.S. Загрузочный сектор всегда заканчивается 55AAh.

Важно обратить внимание на параметр «ReservedSectors » — количество зарезервированных секторов, по смещению 0Eh . В самом начале, я говорил, что загрузочный сектор обычно имеет размер 512 байт, но может быть и больше. Определяется его размер параметром «ReservedSectors », в нашем случае ReservedSectors = 01h , значит загрузочный сектор занимает 1-ин сектор или 512 байт .

2. FAT

После загрузочного сектора с размером 512* ReservedSectors байт , идет таблица FAT1 , её размер определяется двухбайтовым полем — SectorPerFat (16h) загрузочного сектора. В примере выше значение данного поля равняется 0001h или 1 , т.е. один сектор или 512 байт .

Что такое FAT?

Первым делом это аббревиатура – File Allocation Table , означающая «таблица расположение файлов». Это таблица с одним столбцом и 512/2 количеством строк (если размер таблицы FAT – 512 байт или SectorPerFat равен 0001h, как в нашем случае). Каждая строка таблицы FAT занимает 2 байта памяти , поэтому количество строк для нашего случая это 512/2 .

Таблица служит в роли карты по кластерам , каждая её строка характеризует какой либо кластер , первая строка – первый кластер, вторая – второй и так для всех кластеров, что есть в области данных. Перед таблицей стоит дескриптор таблицы F8FFh (то же значение, что и в 15h загрузочного сектора) и заполнитель FFFFh . Далее идут строки таблицы, значения которых могут быть следующие:

  • 0000h - свободный кластер;
  • 0002h-FFEFh - номер следующего элемента в цепочке;
  • FFF0h-FFF6h - зарезервированный;
  • FFF7h - дефектный;
  • FFF8h-FFFFh - последний в цепочке;

Приведу пример HEX кода с пояснением .

Синей рамкой я обозначил таблицу FAT1 , красной таблицу FAT2 (копия таблицы FAT1). Закрашенный зеленый квадратик это дескриптор таблицы F8FFh и заполнитель FFFFh . Не закрашенные квадратики, это строки таблицы. Я не стал обозначать все строки зеленой рамкой, обвел только не нулевые.

Как применяется и зачем нужна FAT, я объясню чуть позже.

3. Корневой каталог

После таблиц FAT идет «корневой каталог ». Это область памяти, содержащая 32-ух байтовые элементы . Каждый элемент описывает , какой либо файл или каталог, находящиеся в корневом каталоге или другим языком «в корне» жесткого диска/флешки. Выходит корневой каталог описывает все то, что есть в корне.

Размер корневого каталога зависит от параметра RootEntries (11h) загрузочного сектора. В нем указывается максимальное число 32-ух байтных элементов в корневом каталоге. Выходит размер каталога это RootEntries * 32 , для нашего случая это 512 * 32 = 16384 байт .

Каждый элемент имеет следующую структуру:

Приведу пример HEX кода с пояснением.

Зеленой рамкой я обозначил область памяти, отвечающая за корневой каталог , синей 32-ух байтные элементы корневого каталога . Не пустые 32-ух байтные элементы я закрасил голубым.

Здесь два не пустых 32-ух байтных элемента , значит, в корневом каталоге храниться два «чего-то» , это могут быть как файлы так и другие каталоги . В данном случае для простоты примера в корне храниться два файла «1.txt » и «test.txt ».

Рассмотрим поближе этих два 32-ух байтных элемента, для удобства я отметил цветами фрагмент HEX кода и соответствующий параметр 32-ух байтного элемента в таблице.

P.S . Если первый байт имени файла заменить на «E5» , то проводник Windows будет считать его как удаленный . Такой файл возможно восстановить, заменив первый символ E5 в имени на прежнее значение. Не уверен до конца, но думаю, что так работает корзина в Windows. Помещая в корзину, операционная система сохраняет, где-то имя файла и заменяет первый байт в имени на E5, а при восстановление присваивает файлу прежнее имя.

P.S . Имена файлов в системе FAT16 хранятся в формате 8.3 . Т.е. 8-байтов выделено для имени и 3-и байта выделено для расширения . Имена кодируются в формате ASCII , один символ это один байт. Поэтому имя не может иметь длину больше чем 8-емь символов , а расширения больше 3-ех . Если имя короче 8-и символов , то недостающие байты заполняются 20h (знак пробела в ASCII коде).

P.S . Напомню, что значение для каждой ячейки считается справа налево, например если написано 00 02 h, то на самом деле это 02 00 h, т.е. 512 в десятичной системе исчисления.

Самый важный для нас параметр находится по адресу 1Аh — «младшее слово первого кластера файлов ». В нем храниться номер кластера, в котором находиться содержимое файл, а это значит мы можем работать с информацией данного файла, т.е. считывать, редактировать его и т.п.

Например «1.txt » храниться в кластере номер 0x0003 или 3 в десятичной системе исчисления. А это значит, что если мы перейдем к кластеру №3 в области данных (напомню, область данных это просто подряд идущие кластеры) мы попадем к содержимому данного файла .

У вас может возникнуть «практический» вопрос, а как найти этот третий кластер? По какому адресу он находиться?

Как найти адрес кластера зная его номер?

Для этого, вам нужно знать какой объем у вас занимает системная область и какого размера кластеры (т.е. сколько секторов (или 512 байт) содержит в себе кластер).

Узнать размер системной области вам поможет следующий рисунок:

Пример для моего случая

Загрузочный сектор имеет объем 512*ReservedSectors байт, в моем случае 512 байт . Далее, таблица FAT у меня занимает один сектор , т.е. 512 байт (т.к. SectroPerFat равен 1). Таблицы две (т.к. NumberOfFATs равен 2), значит две таблицы в сумме 512*2=1024 байт . Размер корневого каталога 512-ть 32-ух значных элементов, т.е. 512*32=16384 байт . Считаем:

512 (загрузочный сектор) + 1024 (две таблицы FAT) + 16384 (корневой каталог) = 17920 байт или 4600 в шестнадцатеричной системе исчисления.

В итоге, в нашем случае область данных начинается с 0x4600 , посмотрим:

Мы видим содержимое, какого то файла, но не нашего. Данные интересующего наc файла (1.txt) хранятся в кластере №3 .

Теперь нужно узнать размер кластера, в этом нам поможет параметр загрузочного сектора – SectorPerCluster (0xD, размер параметра 1 байт). В нашем случае размер кластера 4-е сектора , т.е. 512*4=2048 байт или 800 в шестнадцатеричной системе исчисления. Важно заметить, что кластеры нумеруются с двойки, а не с единицы (!).

Подсчитываем, с какого адреса начинается кластер №3 :

0x4600 (системная область) + 0x800 (второй кластер) = 0x4E00

Подсчитываем, по какому адресу кончается кластер №3 :

0x4E00 (начало кластера №3) + 0x800 (512*4 или размер одного кластера в HEX) = 0x5600

В результате кластер №3 лежит в диапазоне адресов 0x4E00 0x5600.

Посмотрим HEX код

Синий рамкой я обозначил содержимое файла 1.txt . Все, что выше рамки — содержимое другого файла. Пустые области сектора заполняются 0x00.

Так зачем нужна таблица FAT?

Если файл занимает больше чем один кластер (в нашем случае если файл больше 2048 байт), то нам приходит в помощь таблица FAT. Она представляет собой что-то вроде «карты» кластеров. Т.е. когда мы узнаем номер сектора , с которого начинается интересующий нас файл, первом делом мы должны посмотреть такой же номер строки в FAT .

Если строка имеет значение 0xFF8-0xFFFF , то это значит, что это последний кластер для данного файла, т.е. файл занимает всего один кластер .

Если строка имеет значение 0x0002-0xFFEF , то это означает, что файл растянулся на еще один кластер . Цифра означает номер следующего кластера , в котором храниться продолжение файла. Мы должны продолжить считывать файл по данному номеру кластера.

После считывания нового кластера, нужно посмотреть значение строки по данному номеру в FAT. Если значение строки равно 0x FF8-0xFFFF, то это значит, что данный кластер последний в файле. Если 0x0002-0xFFEF, то это номер для следующего кластера, считываем дальше и повторяем действие. Считывание файла это цикл с условием.

Итак мы разобрались с файлами, теперь пришло время разобраться с директориями.

Что такое директория?

Директория для файловой системы FAT16 (да и для многих других) это особый файл с нулевым размером хранящий список своего содержимого .

Допустим, мы добавили в наш образ FAT16 директорию «TEST_DIR » c файлом «in_dir.txt ». Тогда в корневом каталоге появиться новый 32-ух байтный элемент , он описывает директорию также как и файл , но с небольшими отличиями.

Я отметил красным параметры характерные для директорий, это 0x10 – метка каталога и 0x00000000 — размер файла.

Как видно в синем квадрате, директория у нас лежит в кластере №5 , посмотрим что там.

Содержимого «файла» TEST_DIR по сути, это тот же корневой каталог , т.е. набор 32-ух байтных элементов . Я обозначил каждый элемент зеленой рамкой.

В элементах описывается имя файла или каталога, атрибуты и номер кластера в котором лежат его данные. В любой папке, всегда есть два каталога с именем «.» и «..» .

Первый лежит в кластере №5 , т.е. это тот же самый каталог , а второй на кластер номер №0 . Под этим номером понимается «корневой каталог» , т.е. это выход в корневой каталог.

Описание файла «in_dir.txt » стандартное, как и для корневого каталога (см. корневой каталог). Для нас главное, это номер кластера в котором находиться содержимое данного файла (обозначил красным квадратом).

Смотрим кластер №6 и видим содержимое файла «in_dir.txt ». Красной линей я обозначил начало кластера.

Вам будет интересно: