TURBO PASCAL

Новости

Программы   

Turbo Pascal 

Игры

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

Странности

FAQ

Ссылки

Форум

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

Рассылка

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

Об авторе

 

 

3.1.2. Логическая структура дисков

С физической точки зрения все секторы одинаковы — как уже говорилось, их емкость в MS-DOS всегда равна 512 байтам. Однако программы операционной системы закрепляют за каждым сектором некоторые определенные функциИг что позволяет говорить о логической структуре дисков.

Любой диск в ДОС имеет четыре логических части: загрузочный сектор, таблицу распределения файлов, корневой каталог и архивное пространст — во.

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

Загрузочный сектор — это самый первый сектор на самой внешней (нулевой) дорожке. Загрузочный сектор содержит важную информацию о логической структуре диска и короткую программу начальной загрузки. Содержимое загрузочного сектора автоматически считывается в оперативную память после включения ПК, затем управление передается программе начальной загрузки. Эта программа считывает в память нужные части операционной системы и передает им управление. Таким образом, загрузочный сектор нужен прежде всего для начальной загрузки операционной системы.

Начиная с байта с порядковым номером 12, в загрузочном секторе размещается так называемый блок параметров BIOS (BPB), содержащий информацию о длине и расположении остальных логических частей диска и некоторые другие важные параметры. Информация в BPB соответствует следующему типу данных:

type

BPB_Type = record

SectSiz Word; {Количество байт в секторе:

для MS-DOS всегда 512 байт}

ClustSiz Byte; {Количество секторов в кластере} ResSecs Word; {Количество секторов перед FAT) FatCnt Byte; {Количество копий FAT} RootSiz Word; {Количество элементов корневого каталога} TotSecs Word; {Количество секторов на диске} Media Byte; {Дескриптор носителя} FatSize Word {Количество секторов в FAT} end; {BPB_Type}

В этой структуре поле SectSiz, определяющее размер сектора в байтах, для любых операционных систем, совместимых с MS-DOS, всегда имеет значение 512. Дисковые накопители могут читать и записывать секторы и другого размера — 128, 256 или 1024 байта. Такие секторы не могут обслуживаться ДОС и являются для нее «плохими» — при попытке доступа к ним программы ДОС выдадут сообщения об ошибке. Это обстоятельство широко используется для защиты программ от несанкционированного копирования (см. гл.7).

Несколько смежных секторов диска объединяются в группу, называемую кластером. Кластер — это минимальная порция дискового пространства, которую ДОС может выделить файлу. Поле ClustSiz содержит количество секторов в одном кластере. Обычно это число представляет собой степень двойки: 1, 2, 4, 8 и т.д. Причем чем больше объем диска, тем крупнее кластер. Для ГД размер кластера чаще всего составляет 2 сектора (для дискет диаметром 5'/4 дюйма) или 1 сектор (ЗУз дюйма). Для ЖД в кластер обычно входят 4, 8 или 16 секторов.

Поле Media определяет тип носителя информации. Стандартными значениями этого поля могут быть:

$FF - дискета 320 Кбайт (2 стороны, 8 секторов);

$FE - дискета 160 Кбайт (1 сторона, 8 секторов);

$FD - дискета 360 Кбайт (2 стороны, 9 секторов);

$FC - дискета 180 Кбайт (1 сторона, 9 секторов);

$F9 - дискета 1.2 Мбайт (2 стороны, 15 секторов);

$F8 - жесткий диск.

Как показывает практика, содержимое поля Media не всегда соответствует действительности (например, во многих случаях жесткий диск имеет дескриптор $00). Пожалуй, единственным относительно надежным признаком может служить информация в трех младших битах этого поля (табл.3.1).

Таблица 3.1 Значения младших бит поля Media

 

Разряд

Значение

Признак

0

i

Испояьзуются 2 стороны носителя


 

 

0

Используются не 2 стороны

1

1

На дорожке 8 секторов

 

0

На дорожке не 8 секторов

2

1

Съемный носитель информации

 

0

Несъемный носитель информации


Назначение остальных полей ВРВ будет пояснено дальше. Сразу за ВРВ (начиная с байта с номером 25) в загрузочном секторе располагается следующая структура данных:

type

Add_BPB_Type = record

TrkSecs: Word; {Количество секторов на дорожке}

HeadCnt: Word; {Количество головок)

HidnSec: Word {Количество спрятанных секторов}

end; {Ad.d_BPB__Type}

Поле HidnSec содержит общее количество «спрятанных» секторов, т.е. секторов, не относящихся к логической структуре диска (см. ниже). Начиная с версии 4.0 в ДОС вошли средства, поддерживающие жесткие диски большого размера (больше 32 Мбайт). Поэтому для версий 4.х и выше структура данных, располагающихся за ВРВ, такова:

type

Add_BPB_4_Type = record

TrkSecs : Word; {"Количество секторов на дорожке}

HeadCnt : Word; {Количество головок}

HidnSecLo: Word {Младшее слово количества спрятанных секторов}

HidnSecHi: Word {Старшее слово}

TotSecs : Longint {Полное количество секторов на диске) end; {Add._BPB_4_Type}

Признаком того, что используется расширенный блок ВРВ, является значение 41 (символ «)») в 39—м по счету байте загрузочного сектора.

Физический диск может быть разбит на несколько логических разделов, каждый из которых имеет свою логическую структуру. С точки зрения пользователя, каждый раздел выступает как самостоятельный диск и называется логическим диском. Разбивка физического диска на ряд логических устройств осуществляется утилитой FDisk операционной системы или подобными ей несистемными средствами (ADM, Disk Manager и т.п.). Если диск разбит на разделы, в конце загрузочного сектора выделяется 64—байтное поле описателей разделов (по 16 байт на каждый логический диск). Это поле начинается с байта с номером 447 (смещение $1ВЕ от начала сектора). Каждый описатель раздела, создаваемый утилитой FDisk, соответствует такой структуре данных:

type

Part_Type = record

BootF: Byte; {Флаг активности раздела} BegHd: Byte; {Начало раздела - номер головки}

BegSC Word; {Начало раздела - сектор/цилиндр} Sys Byte; {Код системы} EndHd Byte; {Конец раздела - номер головки} EndSC Word; {Конец раздела - сектор/цилиндр} Sees Longint; {Относительный номер начального сектора} Size Longint; {Длина раздела в секторах} end; {Part_Type}

Описываемая логическая структура (загрузочный сектор, таблица распределения файлов и т.д.) создается на каждом логическом диске, т.е. на одном физическом диске существует несколько (по числу логических разделов) загрузочных секторов. Самый первый загрузочный сектор называется главным — именно он используется для начальной загрузки операционной системы. Этот сектор программами BIOS считывается в буфер, начинающийся по адресу $7СОО:$0000, и по этому же адресу передается управление. Получив управление, главный загрузчик просматривает таблицу разделов диска и выбирает раздел (логический диск), имеющий признак активности в поле BootF (если диск активен, это поле имеет значение $80, в противном случае — 0). Затем в память считывается соответствующий загрузочный сектор и управление передается ему. Таким образом, если ЖД разбит на разделы, загрузка ДОС проходит в два этапа. Это позволяет иметь на одном диске несколько загрузчиков для разных операционных систем. Например, активный логический диск может нести сетевую операционную систему, в этом случае его загрузчик осуществляет загрузку этой системы.

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

При анализе главного загрузочного сектора следует иметь в виду важное соглашение ДОС: описатели логических разделов диска построены по принципу связанного списка (см. рис.3.2).

В секторе главного загрузчика используются лишь два описателя Part_Type из четырех возможных: первый описатель (он называется описателем первичного раздела ДОС) определяет физическое расположение и параметры логического диска С, а второй (описатель расширенного раздела ДОС) — расположение на диске следующего описателя. В секторе, соответствующем второму описателю, значащими являются только два поля Part_Type, первое из которых определяет логический диск D, а второе содержит ссылку на новый описатель и т.д.

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

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

h00601.jpg

Рис.3.2. Связанный список описателей жесткого диска

^+—————————————————————————————+

¦ Эта программа считывает ссылочную структуру \ ¦ описателей разделов первого жесткого диска \ ¦ и выводит на экран таблицу логических дисков \ +----------------------------------------------+

;

Uses DOS;

Function ReadSec(Disk,Head: Byte;

CylSec: Word; var Buf): Boolean;

{Обеспечивает считывание абсолютного сектора с помещыо прерывания $13 и возвращает TRUE, если нет ошибки} var

R: Registers;

begin

with R do begin

ah =2; {Код операции чтения}

al =1; {Колич. читаемых секторов}

dl = Disk; {Номер диска: 0,1 - ГД,80,$81 - ЖД}

dh = Head; {Номер головки}

сх = CylSec; {Сектор и цилиндр}

es = seg(Buf); {Адрес буфера в ES:BX}

bx := ofs(Buf) ;

Intr($13,R) ;

ReadSec := (Flags and FCarry)=0 end

end; {ReadSec} {————————————}

type

{Описатель раздела} Part_Type = record

BootF: Byte {Флаг активности раздела} BegHd: Byte {Начало раздела - головка} BegSC: Word {Начало раздела - сектор/цилиндр} Sys : Byte {Код системы} EndHd: Byte {Конец раздела - головка} EndSC: Word {Конец раздела - сектор/цилиндр} Sees : Longint; {Относительный номер начального сектора} Size : Longint; {Длина раздела в секторах} end; {Part_Type} {Структура ссылочного сектора} BootSecType = record

a: array [O..$1BD] of Byte;

Part: array [1..4] of Part_Type;

b: array [1..2] of Byte end;

const

MAXPART = 24; {Максимальное количество логических дисков} var

Boot : BootSecType;

Disk : array [1..MAXPART] of record

Hd: Byte; {Головка} Tr: Word; {Дорожка} Se: Byte; {Сектор} PT: Part_Type;

end;

k,d,j: Byte;

begin

Q := 0; {Номер очередного логического диска} {Читаем главный загрузчик}

if not ReadSec($80,0,1,Boot) then begin

WriteLn('Ошибка чтения главного загрузчика');

Halt end;

{Формируем адрес описателя диска С} Disk[l].Hd := 0;

Disk[l].Tr := 0;

Disk[l].Se := 1;

{Цикл чтения описателей логических дисков} with Boot do repeat

k := 1; {Ищем непустой описатель} while (Part[k] .BegSOO) and (k<4) do inc (k) ;

if k<=4 then

begin {Найден непустой описатель} if cKMAXPART then begin

inc(d); {Номер очередного диска} Disk[d].PT := Part[k] {Сохраняемго описатель} end;

inc(k); {Part[k] -ссылка на следующий

описатель раздела}

if (k<=4) and (Part [k] .BegSCOO) then with Part[k],Disk[d+1] do

begin {Адрес очередного описателя} Hd := BegHd;

Tr := (BegSC and 192) shi 2+BegSC shr 8;

Se := BegSC and 63 end end;

{Продолжаем цикл до ошибки чтения или

пустой ссылки на очередной описатель} until (Part[k].BegSC=0) or (k>4) or

not ReadSec($80,Part[k].BegHd,Part[k].BegSC,Boot) ;

{Выводим таблицу логических дисков} Write(#13#lO#lO'nHCK',' ':8);

for j := 1 to d do

Write(chr(ord('B')+j):10) ;

Write(#13#10'Активный',' ':4);

for j := 1 to d do with Disk[j].Pt do if BootF=$8O then

Write(^a' :10) else

Write('Нет':10) ;

Write(#13#10'Код системы ');

for j := 1 to d do with Disk[j].Pt do Write(Sys:10) ;

Write(#13#10'Объем (байт)');

for j := 1 to d do with Disk[j].Pt do Write(Size*512:lO) ;

WriteLn(#13#10'Начало:') ;

Write(' OTH.сектор');

for j := 1 to d do with Disk[d].Pt do

Write (Sees:10) ;

Write (#13#10' головка ');

for j :== 1 to d do with Disk[j].Pt do

Write(BegHd:10) ;

Write(#13#10' дорожка ');

for j := 1 to d do with Disk[j].Pt do

Write((BegSC and 192) shi 2+ BegSC shr 8:10);

Write (#13#10' сектор ');

for j := 1 to d do with Disk[j].Pt do

Write(BegSC and 63:10);

WriteLn(#13#10'Описатель:') ;

Write (' головка ');

for j := 1 to d do with Disk[j] do

Write(Hd:10) ;

Write (#13#10' дорожка ');

for j := 1 to d do with Disk[j] do

Write (Tr:10) ;

Write (#13#10' сектор ');

for j := 1 to d do with Disk[j] do

Write(Se:lO) ;

WriteLn end.

В этой программе для доступа к физическим секторам используется прерывание BIOS $13, которое подробно описывается в п.3.2.

Поле Sys описателя раздела может иметь одно из значений, указанных в табл.3.2.

Таблица 3.2

Значения поля SYS

 

Значение

Смысл

о

Неизвестная операционная система

1

Операционная система MS-DOS, 12-битная FAT

4

Операционная система MS—DOS, 16-битная FAT

5

Описатель логического раздела


Таблица распределения файлов

За загрузочным сектором располагается так называемая таблица распределения файлов [File Allocation Table — FAT). Эта таблица начинается в секторе BPB.ResSecs и содержит информацию о принадлежности каждого кластера тому или иному файлу. Обычно на диске создается несколько копий FAT (чаще всего две копии), содержимое которых строго идентично. Дублирование информации в нескольких копиях FAT повышает надежность ее хранения. Количество копий FAT и размер каждой копии (в секторах) задаются полями FATCnt и FATSize блока ВРВ.

FAT представляет собой однородную структуру элементов, каждый из которых логически связан с одним кластером диска. Элементы FAT нумеруются, начиная с номера 0, однако первые два элемента используются особым образом, так что кластеры имеют номера, начиная с 2. Чтобы определить, занят ли кластер с номером N, нужно проанализировать N—й элемент FAT: если элемент содержит 0, кластер не занят полезной информацией, в противном случае он содержит ссылку на следующий связанный с ним кластер или специальный признак конца ссылок.

При выделении дискового пространства новому файлу ДОС ищет в FAT первый незанятый кластер и помещает номер этого кластера в связанный с файлом элемент каталога (см. ниже). Если файл целиком умещается в одном кластере, в соответствующий элемент FAT помещается признак занятости, в противном случае — номер того кластера, в котором находится продолжение файла (см. рис.3.3).

h00641.jpg

Рис.3.3. Цепочка ссылок FAT

Как видно из этого рисунка, файл MYFILE. ТХТ начинается в кластере с номером $08 и занимает кластеры $08, $09, $ОА, $ОВ, $15, $16, $17, $19, $1Аи$1В.

В ДОС используются FAT двух типов: с 12— и 16—битными элементами. В первом случае два смежных кластера описываются трехбайтной последовательностью, так что на каждый кластер приходится полтора байта описателя. Такие таблицы используются на дискетах и жестких дисках небольшой емкости (до 10 Мбайт). В 16-битных FAT под каждый описатель выделяются два байта. Начиная с версии 4.0, в загрузочном лекторе со смещением 54 байта от начала располагается 8—байтное поле с символами 'FAT 12' или 'FAT16' в зависимости от типа элементов FAT. Для предыдущих версий ДОС такого явного указания типа FAT нет. Вместо этого используется следующее соглашение: если общее количество кластеров больше 4080 или общее количество секторов больше 20740, FAT использует 16—битные элементы. Значение 4080 определяется как полная емкость 12—разрядного числа (4096) минус 16 номеров, зарезервированных для особых применений (указатели конца цепочки и плохих кластеров). Значение 20740 определяет максимальную емкость логического диска в 10 Мбайт: если диск имеет большую емкость, его FAT оперирует с

16 — разрядными элементами. Замечу, что поле 5ys в описателе логического диска содержит 1 или 4 в зависимости от типа FAT.

Первый байт FAT содержит значение ID, совпадающее с дескриптором носителя Media из ВРВ. Два следующих за ним байта для 12—разрядной или 3 байта для 16—разрядной FAT всегда имеют значение $FF. Таким образом, элементы 0 и 1 FAT используются особым образом, поэтому нумерация кластеров начинается с номера 2. Старшие номера кластеров, начиная с номера $FFO для 12—разрядной и $FFFO для 16—разрядной FAT, используются для специальных целей (в скобках указаны значения для 16—разрядной FAT):

от $FFO ($FFFO) до $FF6 ($FFF6) — зарезервированные кластеры;

$FF7 ($FFF7) — плохой кластер;

от $FF8 ($FFF8) до $FFF ($FFFP) — конец цепочки ссылок.

Структура каталогов

Сразу за последней копией FAT на диске располагается корневой каталог. Содержимое каталога описывает все зарегистрированные в нем подкаталоги и файлы и выводится на экран командой DIR операционной системы. Каждый элемент корневого каталога и всех подкаталогов представлен такой 32 — байтной структурой данных:

type

Dir_Type = record

Name array [1..8] of Char; {Имя файла}

Ext array [1..3] of Char; {Расширение}

FAttr Byte; {Атрибуты файла}

Reserv array [1..10] of Byte; {Резерв}

Time Word; {Время создания}

Date Word; {Дата создания}

FirstC Word; {Номер первого кластера}

Size Longint {Размер файла в байтах}

end; {Dir_Type}

Символы в полях Name и Ext обычно преобразуются к прописным и выравниваются влево, т.е. неиспользуемые символы имени и расширения заполняются ведомыми пробелами. Для имен каталогов оба поля рассматриваются как одно целое, таким образом имя каталога может состоять из 11 символов.

Байт FAttr содержит атрибут файла. ДОС использует значения этого поля, указанные в табл.3.3.

Таблица 3.3 Значения поля FAttr

 

Значение

Смысл

о

Обычный (архивный) файл

i

Файл защищен от изменений и стирания

2

Скрытый файл

4

Системный файл


 

8

Идентификатор тома

$10

Подкаталог

$20

Признак архивации


Допускается комбинация перечисленных признаков. Например, элементы каталогов для системных файлов IBMBIO.COM и IBM.DOS.COM. обычно содержат в поле FAttr значение 7 = 1+24-4, что расшифровы — вается как скрытые системные файлы, защищенные от изменения и стирания.

Поле FirstC указывает на номер кластера, в котором располагается начало файла или каталога. Одновременно этот номер открывает цепочку ссылок FAT, если файл (каталог) не умещается в одном кластере.

Для каждого подкаталога элемент с именем «.» содержит ссылку на корневой каталог, а с именем «..» — на каталог вышележащего уровня. Если файл (подкаталог) удаляется из каталога, первая буква его имени заменяется на символ «х» (#120) и освобождается вся связанная с этим элементом цепочка ссылок FAT. Поскольку поле FirstC сохраняет свое прежнее значение, это дает возможность в некоторых случаях восстановить ошибочно стертый файл.

Признаком конца использующейся части каталога является элемент, в котором первый символ в поле Name имеет значение # 0.

 

Глава 3

Оглавление

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

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

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

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

Hosted by uCoz