TURBO PASCAL

Новости

Программы   

Turbo Pascal 

Игры

Документация   

Странности

FAQ

Ссылки

Форум

Гостевая книга

Рассылка

Благодарности

Об авторе

 

 

3.3.1. Описание модуля

В модуле объявляются описанные ранее типы ВРВ_Туре, Add_BPB_Type и Dir__Type, a также глобальные переменные Disk_Error и Disk_Status, в которых указывается признак ошибки и код ошибки последнего обращения к подпрограммам модуля. Поскольку многие процедуры модуля интенсивно используют информацию о диске, а недокументированная функция $32 ненадежна, в модуле используется специальный тип TDisk, собирающий в единое целое всю необходимую информацию о диске, и создается списочная структура, содержащая информацию о всех жестких дисках ПК.

Тип TDisk открывает доступ к следующей структуре данных:

TDisk = record

Number Byte {Номер диска: 0=А,1=В,...}

TypeD Byte (Тип диска}

AttrD Word {Атрибуты диска}

С у Is Word {Число цилиндров}

Media Byte {Дескриптор носителя}

SectSize Word {Количество байт в секторе}

TotSecs Word {Объем диска в секторах}

ClusSize Byte {Количество секторов в кластере}

MaxClus Word {Максимальный номер кластера}

FATLock Word {Номер 1-го сектора FAT}

FATCnt Byte {Количество FAT}

FATSize Word {Длина FAT в секторах}

FAT16: Boolean {Признак 16-битовой FAT}

RootLock Word {Начало корневого каталога}

RootSize Word {Количество элементов каталога}

DataLock Word {Начальный сектор данных}

end;

В этой структуре поля TypeD, AttrD и Cyls заполняются драйвером диска и соответствуют полям TypeDrv, Attrib и Cylindrs записи IOCTL_Info_Type (см. выше). Поле Media представляет собой дескриптор носителя.

Как уже отмечалось, при вызове IOCTL для дисков большой емкости поле IOCTL_Info_Type.Add. TotSecs содержит 0. В этом случае программа GetDiskInfo модуля F_Disk читает загрузочный сектор диска с помощью прерывания $25 и по его блоку BPB_Add_4_Type определяет полное количество секторов на логическом диске.

Поле FAT16 определяет тип FAT: если это поле содержит значение TRUE, FAT состоит из 16—битных элементов, в противном случае — из 12-битных. Для контроля типа FAT в модуле используется рекомендуемая в MS-DOS проверка: если общее количество кластеров на диске превышает емкость 12-разрядного двоичного числа, т.е. больше 4096, значит FAT использует 16—разрядные элементы, в противном случае — 12-разрядные.

Значение поля RootLock вычисляется по формуле:

RootLock = FATLock + FATCi-it"" FAT Size а поля DataLock — по формуле

DataLock = (RootLock + RootSize*32) div 16+2

При обращениям ко всем процедурам и функциям модуля номер диска соответствует принятому в IOCTL порядку нумерации: 0 — диск А:, 1 — диск В:, 2 — диск С: и т.д. Исключением является вызов процедур GetAbs5ector и SetAbsSector, в которых номер диска соответствует обращению к прерыванию $13: 0 — диск А:, 1 — диск В:, $80 — 1—й ЖД, $81 - 2-й ЖД.

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

Procedure GetListDisk(var List: PListDisk);

Список определяется такой структурой:

type

{Список описателей диска}

PListDisk'= •^TListDisk;

TListDisk = record

Disklnfo: TDisk; (Описатель диска} NextDisk: PListDisk {Ссылка на следующий}

end;

Поскольку параметры ГД могут меняться от дискеты к дискете, информация о них не заносится в список. В модуле предусмотрена следующая глобальная переменная:

const

Disks: PListDisk = NIL.

Полезно перед самым первым обращением к подпрограммам модуля F_Disk сформировать список таким образом:

GetListDisk(Disks).

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

Работа с диском на физическом уровне 85

Процедура FreeListDisk. С помощью этой процедуры из динамической памяти удаляется связанный список дисковых описателей, ранее созданный процедурой GetListDisk. Заголовок:

Procedure FreeListDisk(var List: PListDisk) ;

Функция ChanqeDiskette. Возвращает логический признак, указывающий, изменялось ли положение запора на приводе гибкого диска с момента последней операции чтения/записи (True — менялось). Эта информация сохраняется контроллером ГД и возвращается функцией 22 прерывания $13. Заголовок функции:

Function ChangeDiskette(Disk: Byte): Boolean;

Процедура GetAbsSector. Осуществляет чтение содержимого нужного физического сектора диска. Заголовок:

Procedure GetAbsSector(Disk,Head: Byte; CSec: Word;

var Buffer).

Параметры вызова функции соответствуют параметрам обращения к прерыванию $13: Disk — номер физического диска (0 = 1—й ГД, 1 = 2—й ГД, $80 = 1-й ЖД, $81 = 2-й ЖД); Head — номер головки (поверхности); нумерация начинается с нуля; CSec — номер цилиндра и сектора в виде 16—разрядного упакованного слова (нумерация цилиндров начинается с нуля, а секторов — с единицы); Buffer — переменная длиной 512 байт, в которую помещается содержимое прочитанного сектора.

Эта процедура использует прерывание BIOS $13. Она игнорирует логические разделы ЖД.

Функция GetCluster. Возвращает номер кластера для указанного номера сектора. Заголовок:

Function GetCluster (Disk: Byte; Sector: Word): Word.

Здесь Disk — номер диска; Sector — номер сектора.

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

Функция GetDefaultDrv. Возвращает номер диска, который установлен в ДОС как диск по умолчанию (текущий диск). Заголовок:

Function GetDefaultDrv: Byte.

Процедура GetDirItem. Возвращает элемент каталога для указанного файла. Заголовок:

Function GetDirItem(FileName: String; var Item: Dir_Type).

Здесь FileName — строковое выражение, содержащее имя файла (можно задавать имя с предшествующим ему маршрутом поиска); Item —

переменная типа Dir_Type, в которой возвращается соответствующий элемент каталога.

Если не найден каталог, содержащий заданный файлг в переменной Disk_Error устанавливается значение TRUE, а в переменной Disk_Status — значение $FFFF (65535) .

Процедура GetDirSector. Возвращает номер сектора, в котором начинается указанный каталог, или 0, если каталог не найден. Заголовок:

Procedure GetDirSector (Path: String; var Disk: Byte;

var Dirs, DirSize: Word).

Здесь Path — выражение строкового типа, в котором указывается полный путь к каталогу; можно задать пустую строку (т.е. строку нулевой длины) для ссылки на текущий каталог; Disk — переменная типа Byte, в которой возвращается номер диска; DirS — переменная типа Word, возвращает 0, если каталог не найден, или номер сектора, в котором начинается каталог; DirSize — переменная типа Word, возвращает количество элементов каталога.

Процедура GetDiskInfo. Возвращает информацию о диске. Заголовок:

Procedure GetDiskInfo(Disk: Byte; var Info: TDisk).

Здесь Disk — номер диска; Info — переменная типа TDisk, в которой возвращается информация о диске.

При каждом обращении к этой функции, а к ней обращаются многие другие подпрограммы модуля, вначале проверяется связанный список, ассоциированный с глобальной переменной Disks: если этот список пуст или в нем не содержится сведений о нужном диске, осуществляется общий вызов IOCTL с требованием построить ВРВ, по результатам которого и формируется переменная Info. Таким образом, для ускорения доступа к диску полезно вначале сформировать процедурой GetListDisk связанный список дисковых описателей и поместить начало этого списка в переменную Disks.

функция GetDiskNumber. Возвращает номер логического диска по указанной букве его имени. Заголовок:

Function GetDiskNumber(Name: Char): Byte.

Здесь Name — имя диска (А, В, С и т.д.).

функция возвращает значение 255 ($FF), если указано недопустимое имя (если Name не принадлежит множеству 'A'..'Z или задает имя несуществующего логического диска).

Функция GetFATItem. Возвращает содержимое нужного элемента таблицы распределения файлов. Заголовок:

Procedure GetFATItem(Disk: Byte; Item: Word): Word. Здесь Disk — номер диска; Item — номер элемента FAT.

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

В случае 12-битной ГАГ значение, возвращаемое функцией CctFATtem, приводится к 16-битному формату: если элемент FAT имеет значение больше, чем $FFO, к этому значению прибавляется код $FOOO. Это связано с тем, что 16 старших значений элементов FAT ($FFFO. . .$FFFF для 16-битной и $FFO. . .$FFF для 12-битной FAT} используются ДОС для специальных целей — для указания конца цепочки FAT (коды $FF8. . ,$FFF для 12-битной и $FFF8. . ,$FFFF для 16—битной FAT), сбойных кластеров (коды $FF7 и $FFF7) и резервных кластеров (коды $FFO...$FF6 и $FFFO. . .$FFF6).

Процедура GetIOCTLInfo. Реализует общий вызов IOCTL в формате функции $60 (дать информацию об устройстве). Заголовок:

Procedure GetIOCTLInfo(Disk: Byte; var Info: IOCTL_Type).

Здесь Disk — номер диска; Info — Переменная типа IOCTL__Type, в которой возвращается информация о диске.

Эта процедура используется для построения ВРВ при обращении к процедуре GetDiskInfo.

Процедура GetMasterBoot. Используется для доступа к главному загрузочному сектору, что может оказаться полезным в программах защиты от компьютерных вирусов (см. гл.6). Заголовок:

Procedure GetMasterBoot(var Buf).

Здесь Buf — любая переменная длиной не менее 512 байт; в эту переменную помещается содержимое главного загрузочного сектора.

Главный (системный) загрузчик всегда располагается на первом ЖД (MS-DOS может обсуживать один или два жестких диска) в самом первом секторе нулевой дорожки. Доступ к этому сектору можно получить только с помощью прерывания $13. Доступ к остальным частям любого диска реализуется функциями ReadSector/WriteSector (см. ниже).

Функция GetMaxDrv. Возвращает общее количество логических дисков минус 1, т.е. максимально возможный номер диска. Заголовок:

Function GetMaxDrv: Byte.

Для определения количества дисков используется функция $ОЕ ДОС (установка диска по умолчанию), которая в регистре AL возвращает требуемое значение. Предварительно с помощью функции $19 программа получает номер текущего диска (диска по умолчанию), поэтому обращение к процедуре не меняет настройку ДОС.

Функция GetSector. Преобразует номер кластера в номер сектора для указанного диска. Заголовок:

Function GetSector(Disk: Byte; Cluster: Word): Word.

Здесь Disk — номер диска; Cluster — номер кластера.

Функция возвращает значение $FFFF (65535), если задан неверный номер кластера (меньше 2 или больше MaxClus] или несуществующий диск.

Функция PackCylSec. Преобразует номер сектора и номер цилиндра в формат слова, используемого при обращении к функциям прерывания $13. Заголовок:

Function PackCylSec(Cyl,Sec: Word): Word. Здесь Cyl — номер цилиндра; Sec — номер сектора.

Процедура ReadSector. Осуществляет чтение одного или нескольких последовательных секторов с дискового носителя в оперативную память. Заголовок:

Procedure ReadSector (Disk: Byte; Sector, Count: Word;

var Buffer).

Здесь Disk — номер диска; Sector — номер дискового сектора, с которого начинается чтение информации; Count — количество читаемых секторов; Buffer — переменная любого типа размером не менее Counf'512 байт, в которую будет записана прочитанная информация.

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

В процедуре предусмотрена работа с дисками большой емкости.

Процедура SetAbsSector. Реализует запись на диск сектора по его абсолютному номеру с помощью прерывания $13. Заголовок:

Procedure SetAbsSector (Disk, Head: Byte; CSec: Word;

var Buffer).

Здесь Disk — номер физического диска (0 = 1 — и ГД, 1 = 2 — и ГД, $ 8 О = 1—й ЖД, $81 = 2—и ЖД); Head — номер головки (поверхности), нумерация начинается с нуля; С5ес — номер цилиндра и сектора в виде 16—разрядного упакованного слова (нумерация цилиндров начинается с нуля, а секторов — с единицы); Buffer — переменная длиной 512 байт, содержимое которой будет записано на диск.

Процедура SetDefaultDrv. Устанавливает указанный диск в качестве текущего (умалчиваемого) диска. Заголовок:

Procedure SetDefaultDrv(Disk: Byte). Здесь Disk номер диска.

Процедура Set FAT Item. Записывает нужное значение в таблицу FAT и во все ее (таблицы) копии. Заголовок:

procedure SetFATItem(Disk: Byte; Cluster,Item: Word).

Здесь Disk — номер диска; Cluster — номер элемента FAT; Item — новое значение элемента.

Использование этой процедуры требует предельной осторожности, т.к. ошибочное изменение состояния FAT может привести к катастрофическим последствиям.

Как уже говорилось, на диске создается несколько следующих друг за другом копий FAT. Это обстоятельство приходится учитывать при записи скорректированного состояния FAT на диск в случае, если FAT использует 12-битные элементы. Вызвано это тем, что в целях уменьшения требуемой памяти и упрощения алгоритма в процедуре считывается не вся FAT, а лишь та тройка секторов, в которой находится изменяемый элемент (три смежных сектора гарантируют цикличность изменения адресов FAT — в одном 512—байтном секторе сохраняется информация о 2*512/3 = 341^3 12—разрядных элементах FAT). После коррекции копии FAT в памяти ее нужно записать на диск, предварительно исключив из записи те секторы, которые, возможно, не принадлежат первой копии FAT. Если этого не сделать, то при изменении последних элементов таблицы может быть испорчен корневой каталог.

Процедура SetMasterBoot. Записывает новое значение главного (системного) загрузчика. Заголовок:

Procedure SetMasterBoot(var Buf).

Здесь Buf — произвольная переменная; первые 512 байт этой переменной записываются в первый сектор нулевой дорожки первого жесткого диска.

Эта процедура может пригодиться в программах защиты от компьютерных вирусов (см. гл.6). Я настоятельно рекомендую не экспериментировать с процедурой SetMasterBoot, т.к. это может привести к разрушению системного загрузчика и Ваш ПК перестанет нормально функционировать.

Процедура UnpackCylSec. Преобразует упакованный формат ци— линдр/сектор, используемый при обращениях к прерыванию $13, к двум 16—разрядным словам, т.е. эта процедура осуществляет обратные действия по сравнению с функцией PackCylSec. Заголовок:

Procedure UnpackCylSec(CSec: Word; var Cyl,Sec: Word).

Здесь CSec — упакованный формат цилиндр/сектор; Cyl — номер цилиндра; Sec — номер сектора.

Процедура WriteSector. Записывает содержимое переменной любого типа в один или несколько смежных секторов. Заголовок:

Procedure WriteSector (Disk: Byte; Sector, Count: Word;

var Buffer);

Здесь Disk — номер диска; Sector — номер дискового сектора, с которого начинается запись информации; Count — количество записываемых секторов; Buffer ~ переменная любого типа, содержимое которой требуется записать на диск.

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

 

Глава 3

Оглавление

На первую страницу

Rambler's Top100 Rambler's Top100
PROext: Top 1000

(с)Все права защищены

По всем интересующим вопросам прошу писать на электронный адрес

Hosted by uCoz