Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Методическое пособие - Файловые системы FAT

.pdf
Скачиваний:
94
Добавлен:
02.05.2014
Размер:
440.35 Кб
Скачать

При создании каталога в него заносятся два специальных дескриптора, содержащих в поле имени “.” и “..”. Они выглядят как дескрипторы для подкаталогов. На самом деле “.” указывает на содержащий его каталог, т.е. каталог имеет ссылку сам на себя. Второй специальный дескриптор с именем “..” указывает на каталог более высокого уровня.

Если в поле номера первого занимаемого кластера дескриптора с именем “..” находится нулевое значение, это означает, что данный каталог содержится в корневом каталоге.

Таким образом, в древовидной структуре каталогов имеются ссылки как в прямом, так и в обратном направлении.

При удалении файла первый байт его имени заменяется на байт E5h (символ 'х'). Все кластеры, распределенные файлу, отмечаются в FAT как свободные. Если вы только что удалили файл, его еще можно восстановить, так как в дескрипторе сохранились все поля, кроме первого байта имени файла. Но если на диск записать новые файлы, то содержимое кластеров удаленного файла будет изменено и восстановление станет невозможным.

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

FAT

FAT

Корневой

Область

Блок параметров

(копия)

каталог

файлов

BIOS (BPB)

 

 

 

 

 

 

 

 

 

Рис.9. Области логического диска

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

В FAT файлам всегда выделяется целое число кластеров. Например, на 1,2- Гбайт жестком диске с 32-Кбайт кластерами в каталоге может быть указано, что размер текстового файла, содержащего слова "hello, world", составляет всего 12 байт, но на самом деле этот файл занимает 32 Кбайт дискового пространства. Неиспользованная часть кластера называется потерянным местом (slack). В небольших файлах почти весь кластер может быть потерянным местом, а в среднем потери составляют половину размера кластера.

Структура FAT32

FAT16 перестала устраивать пользователей, прежде всего, из-за ограничений накладываемых ей на емкость дисков. Учитывая это, фирма Microsoft разработала новое расширение системы FAT - FAT32.

Рассмотрим изменения, внесенные в структуру FAT32.

Блок параметров BIOS FAT32

Таблица 9

(0)

2

sect_siz

Количество байтов в одном секторе диска.

(+2)

1

clustsiz

Количество секторов в одном кластере.

(+3)

2

res_sect

Количество зарезервированных секторов.

(+5)

1

fat_cnt

Количество таблиц FAT.

 

 

 

Максимальное количество дескрипторов файлов,

(+6)

2

root_siz

содержащихся в корневом каталоге диска. Драйверы

 

 

 

FAT32 игнорируют это поле.

(+8)

2

tot_sect

Общее количество секторов на носителе данных (в

разделе).

 

 

 

(+10)

1

media

Байт-описатель среды носителя данных.

 

 

 

Количество секторов, занимаемых одной копией FAT.

(+11)

2

fat_size

Значение установлено в 0. Вместо него используются

 

 

 

поля BigSectorsPerFat и BigSectorsPerFatHi

(+13)

2

sectors

Количество секторов на дорожке.

(+15)

2

heads

Количество сторон (головок).

 

 

 

Количество секторов на томе, расположенных до

(+17)

4

HiddenSectors

загрузочного сектора. Это значение используется для

вычисления смещения корневой директории и области

 

 

 

данных.

(+21)

4

Tot_secs

Общее количество секторов на логическом диске

(+25)

4

BigSectorsPerFat

Число секторов под FAT

 

 

 

Флаги описания драйвера. 8 бит (7-ой разряд) этого

 

 

 

поля показывает, будет ли информация записываемая в

(+29)

2

ExtFlags

активную FAT, записываться во все копии FAT. Если

этот бит установлен то, 4 младшие бита содержат

 

 

 

 

 

 

номер активной FAT.

 

 

 

Биты с 4 по 6 и с 8 по 15 зарезервированы.

(+31)

2

FS_Version

Номер версии файловой системы.

(+33)

4

RootDirStrtClus

Номер первого кластера корневого каталога

 

 

 

Номер сектора, содержащего структуру

(+37)

2

FSInfoSec

BIGFATBOOTFSINFO. Если этот сектор отсутствует

 

 

 

значение поля установлено в 0FFFFh.

 

 

 

Номер резервного загрузочного (backup boot) сектора.

(+39)

2

BkUpBootSec

Если этот сектор отсутствует значение поля

 

 

 

установлено в 0FFFFh

(+41)

12

Reserved

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

Блок начальной загрузки на разделах с FAT32 был увеличен до 2 секторов. Это связано с тем, что блок параметров BIOS в FAT32 дополнен новыми элементами (таблица 9).

Структура BIGFATBOOTFSINFO содержит информацию о файловой системе на томе FAT32. Структура содержит поля, указанные в таблице 10.

 

 

Структура BIGFATBOOTFSINFO

Таблица 10

Смещение

Размер

Псевдоимя

Содержание

 

 

 

 

 

(+0)

4

Sig

Сигнатура сектора информации о файловой

системе. Содержит значение 61417272h.

 

 

 

 

 

 

Количество свободных кластеров на диске.

(+4)

4

Free_clus_cnt

Установлено в -1, если количество свободных

 

 

 

кластеров неизвестно.

 

(+8)

4

Next_free_clus

Номер последнего освобожденного кластера.

(+12)

12

Resvd

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

 

FDISK создает копию загрузочного блока, начиная с 6-го сектора раздела. И если при загрузке возникают проблемы с чтением загрузочного блока, то считывается и загружается копия.

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

Чтобы обеспечить возможность работы с возросшим числом кластеров, в записи каталога для каждого файла должно выделяться 4 байт для начального кластера файла (вместо 2 байт в системе FAT16). Традиционно каждая запись в каталоге состоит из 32 байт (таблица 7). В середине этой записи 10 байт не используются (байты с 12-го по 21-й). Microsoft зарезервировала их для своих собственных нужд в будущем. Два из них, а именно 20-й и 21-й, теперь используются как дополнительные байты, необходимые для указания начального кластера в системе FAT32.

Еще одно изменение состоит в том, что корневой каталог, раньше имевший фиксированный размер и строго определенное место на диске, теперь можно свободно перемещать и наращивать по мере необходимости подобно подкаталогу. Корневой каталог в FAT32 представлен в виде обычной цепочки кластеров. Начальный кластер корневого каталога теперь указан в блоке параметров BIOS по смещению +35 (таблица 9). Таким образом, теперь не существует ограничений на число записей в корневом каталоге. Это особенно важно, поскольку под каждое длинное имя файла используется несколько записей каталога.

Средства работы с разделами

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

В ОС направления Windows Me для доступа к сектору на томе можно воспользоваться прерыванием 21h функцией 7305h. Это прерывание вызывается функцией

DeviceIoControl с кодом управления VWIN32_DIOC_DOS_ DRIVEINFO. Предва-

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

#include <windows.h>

 

 

 

#define VWIN32_DIOC_DOS_DRIVEINFO

6

typedef

struct

_DIOC_REGISTERS {

DWORD reg_EBX;

 

 

DWORD reg_EDX;

 

 

DWORD reg_ECX;

 

 

DWORD reg_EAX;

 

 

DWORD reg_EDI;

 

 

 

DWORD reg_ESI;

 

 

 

DWORD reg_Flags;

 

 

} DIOC_REGISTERS, *PDIOC_REGISTERS;

#define CARRY_FLAG 0x1

 

 

#pragma pack(1)

 

 

 

typedef

struct

_DISKIO {

 

DWORD dwStartSector;

//номер начального логического сектора

WORD

wSectors;

 

// количество секторов для чтения

DWORD dwBuffer;

// адрес буфера для чтения

} DISKIO, * PDISKIO;

 

 

#pragma pack()

 

 

 

// функция чтения / записи секторов

 

BOOL ReadWriteSectors (HANDLE hDev,

// Дескриптор виртуального драйвера

BYTE

bDrive,

 

// Номер драйвера 1 - A, 2 - B и т.д

DWORD dwStartSector,

// Начальный сектор чтения

WORD wSectors,

// Количество считываемых секторов

LPBYTE lpSectBuff,// Буфер под считываемые данные

BOOL flgRead)

 

// Признак чтения

{

 

 

 

 

BOOL

fResult;

 

 

 

DWORD

cb;

 

 

 

DIOC_REGISTERS reg = {0};

 

 

DISKIO

dio;

 

 

 

dio.dwStartSector = dwStartSector;

// задаем начальный сектор

dio.wSectors = wSectors;

 

// задаем количество секторов

dio.dwBuffer

= (DWORD)lpSectBuff;

// задаем адрес буфера

reg.reg_EAX = 0x7305;

// задаем номер функции чтения логического сектора

reg.reg_EBX = (DWORD)&dio;

// задаем адрес структуры для чтения диска

reg.reg_ECX = -1;

 

 

reg.reg_EDX = bDrive;

// задаем номер диска 1=A, 2=B, и т.д.

if(flgRead) reg.reg_ESI = 0x6000;

// признак чтения сектора

else reg.reg_ESI = 0x6001;

 

// признак записи сектора

fResult = DeviceIoControl(hDev, VWIN32_DIOC_DOS_DRIVEINFO, &reg, sizeof(reg), &reg, sizeof(reg), &cb, 0);

// если вызов DeviceIoControl был успешен Result будет равен 1, иначе 0. fResult = fResult && !(reg.reg_Flags & CARRY_FLAG);

return fResult;

}

// функция чтения первого сектора тома

void ReadFirstSector(void)

{

HANDLE hDev; BYTE buf[512];

// получаем дескриптор виртуального драйвера

hDev = CreateFileA("\\\\.\\VWIN32", 0, 0, 0, 0, FILE_FLAG_DELETE_ON_CLOSE, 0); if (hDev != INVALID_HANDLE_VALUE)

{

ReadWriteSectors (hDev, 1, 0, 1, buf, TRUE);

CloseHandle(hDev); // закрываем драйвер

}

}

Кроме того, в ОС направления Windows Me для чтения блока параметров BIOS можно использовать прерыванием 21h функцией 440Dh с минор кодом 60h.

#include <windows.h>

 

 

 

 

#define VWIN32_DIOC_DOS_IOCTL

1

typedef

struct

 

 

_DIOC_REGISTERS {

DWORD reg_EBX;

 

 

 

 

DWORD reg_EDX;

 

 

 

 

DWORD reg_ECX;

 

 

 

 

DWORD reg_EAX;

 

 

 

 

DWORD reg_EDI;

 

 

 

 

DWORD reg_ESI;

 

 

 

 

DWORD reg_Flags;

 

 

 

 

} DIOC_REGISTERS, *PDIOC_REGISTERS;

 

#define CARRY_FLAG 0x1

 

#pragma pack(1)

 

 

 

 

 

typedef

struct

 

 

tagEA_DEVICEPARAMS

{

 

 

 

 

 

BYTE bSpecFunc;

 

// специальная функция

BYTE bDevType;

 

// тип устройства

 

WORD wDevAttr;

 

 

// атрибуты устройства

WORD wCylinders;

 

 

// количества цилиндров

BYTE bMediaType;

 

 

// тип среды

 

// блок параметров BIOS (BPB)

 

WORD wBytesPerSec;

 

// байтов в секторе

 

BYTE bSecPerClust;

 

 

// секторов в кластере

WORD wResSectors;

 

 

// количество зарезервированных секторов

BYTE bFATs;

 

// количества FAT

 

WORD wRootDirEnts;

// количества элементов корневой директории

WORD wSectors;

 

// всего секторов

 

BYTE bMedia;

// описатель среды

 

WORD wFATsecs;

 

 

// количество секторов, занятых FAT

WORD wSecPerTrack;

// количество секторов на дорожке

WORD wHeads;

 

// количество головок

 

LONG dwHiddenSect;

 

// количество скрытых секторов

LONG dwBigTotalSectors; // всего секторов на томе

LONG dwBigSectorsPerFat; // количество секторов, занятых FAT

WORD dwExtFlags;

 

 

// флаг описания драйвера

WORD dwFS_Version;

 

// номер версии файловой системы

LONG dwRootDirStrtClus; // начальный кластер корневой директории

WORD dwFSInfoSec; // Номер сектора, содержащего структуру BIGFATBOOTFSINFO. WORD dwBkUpBootSec; // номер сектора, содержащего копию загрузочного сектора

BYTE Reserved[12];

} EA_DEVICEPARAMS, FAR * LP_EA_DEVICEPARAMS; #pragma pack()

BOOL GetDeviceParameters (int nDrive)

{

HANDLE hDev;

BOOL fResult; DWORD cb;

DIOC_REGISTERS reg = {0}; EA_DEVICEPARAMS dp;

// получаем дескриптор виртуального драйвера

hDev = CreateFile("\\\\.\\VWIN32", 0, 0, 0, 0, FILE_FLAG_DELETE_ON_CLOSE, 0);

if (hDev != INVALID_HANDLE_VALUE)

{

reg.reg_EAX = 0x440D; // задаем номер функции чтения логического сектора reg.reg_EBX = nDrive; // задаем номер диска 1=A, 2=B, и т.д.

reg.reg_ECX = 0x4860; reg.reg_EDX = (DWORD)&dp

fResult = DeviceIoControl(hDev, VWIN32_DIOC_DOS_DRIVEINFO, &reg, sizeof(reg), &reg, sizeof(reg), &cb, 0);

// если вызов DeviceIoControl был успешен Result будет равен 1, иначе 0. fResult = fResult && !(reg.reg_Flags & CARRY_FLAG); CloseHandle(hDev); // закрываем драйвер

return fResult;

}

}

Для ОС направления Windows 2000 во всех случаях можно воспользоваться функциями CreateFile, ReadFile и WriteFile.

#include <winioctl.h>

HANDLE hDrive = CreateFile("\\\\.\\C:", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,NULL, OPEN_EXISTING, 0, NULL);

if(hDrive == INVALID_HANDLE_VALUE) printf("Error open volume"); else

{

BYTE sec_buf[512]; DWORD dwBytesRead; int offset_buff;

// Читаем 1-й сектор тома...

ReadFile(hDrive, sec_buf, 512, &dwBytesRead, NULL);

// закрываем устройство

CloseHandle(hDrive);

}

Заключение

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

Библиографический список

1.Барри Саймон. Файловая система FAT32 для Windows 95. PC Magazine, Ап-

рель 8, 1997, стр.279.

2.Хелен Кастер. Основы Windows NT и NTFS/Пер. с англ. — М: Издательский отдел “Русская редакция” ТОО “Channel Trading Ltd.”, 1996.—440 с.

3.Ресурсы Windows NT: пер. с англ. — СПб.: BHV — Санкт-Петербург, 1996.

720 с.

4.Фролов А.В., Фролов Г.В. Программирование для Windows NT. — М.:

ДИАЛОГ-МИФИ, 1996. – 272 с. Т. 26.

5.Фролов А.В., Фролов Г.В. Программирование для Windows NT. — М.:

ДИАЛОГ-МИФИ, 1997. – 271 с. Т. 27.

6.Нортон П. Персональный компьютер фирмы IBM и операционная система

MS-DOS: Пер. с англ. — М.: Радио и связь, 1991. С. 416.