этой главе обсуждаются некоторые ключевые средства DOS, которые
важны для написания TSR. Вы должны отдавать себе отчет, что боль-
шая часть этих материалов не описана и, следовательно, может быть
изменена.
Структуры данных ввода/вывода DOS
DOS поддерживает много важных для TSR структур. Некоторые из
них являются общими для всех резидентных программ. Например, DOS
поддерживает две системные таблицы файлов, одна для обработчика
доступа, другая для функционирования блока управления файлом
(FCB). Все программы имеют доступ к одним и тем же системным таб-
лицам. Другие структуры данных индивидуальны для каждой програм-
мы. Например, каждая программа имеет свой сегмент программного
префикса (PSP).
Когда DOS загружает программу, она записывает PSP этой прог-
раммы в общие переменные (В DOS 3.10 эти переменные размещены со
смещением 02DEh в сегменте DOS). Программа, чей PSP записан в
сегменте DOS, становится текущей. Как только IBMBIO загрузила яд-
ро системы, имеется всегда одна и только одна текущая программа.
Когда программа делает запрос на ввод/вывод, она передает
DOS описатель или блок управления файлом. Для обработки описателя
файла DOS должен найти структуру данных, известную как рабочая
таблица файлов (JFT). Каждый PSP содержит адрес JFT на смещении
34h (Листинг 4-5 "Структура PSP"). Для нахождения текущей JFT DOS
проcматривает PSP текущей программ. Обычно JFT начинается со сме-
щения 18h PSP (т.е. адрес JFT указывает другое смещение внутри
PSP). Для получения номера системного файла (SFN), который, в
свою очередь, является индексом в системной таблице файлов, DOS
использует описатель как индекс в JFT. Одно из неописанных полей
внутри FCB содержит номер системного файла(FSN); этот SFN являет-
ся индексом системной таблицы файлов FCB. Эта системная таблица
указывает DOS, как найти устройство.
"Список списков"
DOS записывает адреса системных таблиц как описателей так и
FCB в структуру данных, известную как "список списков". Эта
структура данных содержит и другую важную информацию. Вашему TSR
может понадобиться просмотреть содержимое этого списка или неко-
торые структуры данных, на которые он указывает. Недокументиро-
ванная функция AH=52h прерывания int 21h возвращает адрес списка
списков в паре регистров ES:BX. Фрагмент программы, приведенной
на листинге 4-11 показывает, как найти этот список.
- 4-18 -
Листинг 4-11. Поиск списка списков
----------------------------------------------------------------
ListAddr DW 0,0
mov ah,52h ; запрос DOS, где он размешен
int 21h ; (недокументированная функция)
mov ListAddr,bx ; адрес возвращается в ex:bx
mov ListAddr+2,es
----------------------------------------------------------------
Короче говоря, имеются вполне определенные функции для раз-
ных входов в список списков. Блочное устройство (обычно диск) за-
писывает информацию о структуре файловой системы в блок управле-
ния устройством (DCB). Данные DCB обычно включают размер диска,
количество входов в корневой директорий, количество FAT и т.д.
DOS записывает адрес системных часов в качестве оптимизатора про-
изводительности. Вдобавок к обработке запросов о времени и дате,
DOS записывает временные метки при каждой записи FCB и затем за-
писывает время самого последнего обращения к записи описателя.
DOS использует сохраненный адрес клавиатуры для проверки сигнала
break и для сообщения об ошибках "деление на нуль". DOS предпола-
гает, что клавиатура имеет ISR int 1Bh, так что ISR клавиатуры
может обрабатывать break немедленно. Для операций над блочными
устройствами DOS использует текущий директорий. DOS поддерживает
список используемых кэш-блоков для обработки запросов на чте-
ние/запись отдельных блоков и для обращения к блокам директория и
FAT. Длина каждого кэш-блока указана в DOS_W_MaxSector. Заголов-
ками для таблиц описателей и FCB файловой системы являются, соот-
ветственно, DOS_D_HDLSFT и DOS_D_FCBSFT. Листинг 4-12 показывает
содержимое этого списка.
Листинг 4-12. Формат списка списков
----------------------------------------------------------------
DOS STRUC
DOS_D_DCB DD 0 ; начало списка для последовательности
; блоков управления устройством (DCВ)
DOS_D_HDLSFT DD 0 ; начало списка описателя SFT
DOS_D_Clock DD 0 ; оглавление устройства для CurClk
DOS_D_Console DD 0 ; оглавление устройства для консоли
DOS_W_MaxSector DW 0 ; размер наибольшего сектора
DOS_D_Cache DD 0 ; начало списка для блоков управления
; кеш (CCB)
DOS_D_CDS DD 0 ; адрес структуры текущего каталога
DOS_D_FCBSFT DD 0 ; начало списка FCB SFT
DOS_W_Unknown DW 0 ; неизвестно
DOS_B_DriveCountDB 0 ; максимальное количество драйверов
; (значение устанавливается по lastdrive=)
DOS_B_LastDrive DB 0 ; текущее количество драйверов
DOS ENDS
----------------------------------------------------------------
Системная таблица файлов
Из всех структур данных, за которыми обращаются в список
- 4-19 -
списков, для TSR наиболее важны входы в таблицу системы файлов.
Информация, которую содержат эти входы, влияет на способ обработ-
ки резидентными программами запросов на ввод/вывод. Эти структуры
данных, которые размещены во внешней области данных DOS, содержат
один или несколько блоков. Каждый блок содержит заголовок, кото-
рый указывает на следующий блок, и несколько входов таблицы фай-
ловой системы. Каждый вход SFT является структурой данных.
Длина заголовка 6 байтов. Первое поле - это двойное слово,
которое содержит адрес следующего блока в таблице файловой систе-
мы или единицу для обозначения конца списка. Второе поле - слово,
которое указывает количество входов системы. Листинг 4-13 иллюст-
рирует структуру SFT.
Листинг 4-13. Оглавление блока таблицы файлов системы
----------------------------------------------------------------
SFTTBL STRUC
SFTTBL_D_Next DD 0
SFTTBL_W Count DW 0
SFTTBL ENDS
SFTTBL_K_Size EQU SIZE SFTTBL ; определено для дальнейшего
; использования
----------------------------------------------------------------
Многие поля каждого входа SFT важны только для блоковых уст-
ройств, но значение счетчика обращений и поле хозяина PSP непос-
редственно касаются TSR. Когда DOS открывает файл, он помещает
вход в таблицу файловой системы и записывает текущий PSP в поле
хозяина PSP со смещением 22h. Так как только владелец файла может
закрыть его, то перед запросом к DOS закрыть файл, Вы должны быть
уверены, что именно Ваш PSP установлен в качестве текущей прог-
раммы. Так же перед окончанием работы Вы должны восстановить PSP
первоначальной программы переднего плана.
Счетчик обращений является первым полем входа и содержит
слово, в котором записано, сколько раз файл или устройство были
открыты. Перед размещением нового входа, DOS проверяет все су-
ществующие входы для проверки, не открыт ли уже файл или устройс-
тво, к которым сделан запрос. Если вход SFT уже существует, DOS
увеличивает счетчик обращений перед размещением нового входа. DOS
уменьшает счетчик обращений, когда файл/устройство закрываются,
но не освобождает вход до обнуления счетчика обращений.
Когда DOS обрабатывает запрос на открытие или создание (че-
рез FCB или описатель), он записывает текущий PSP в поле хозяина
SFT и записывает биты состояния (означающие запрос на открытие в
исключительном режиме или в режиме чтения) в поле режима SFT, ес-
ли файл не был открыт раньше. Биты состояния определяют, какой
тип доступа будет разрешен.
Листинг 4-14. Структура входа SFT
----------------------------------------------------------------
SFT STRUC
SFT_W_RefCnt DW 0 ; [00] счетчик обращений
SFT_W_Mode DW 0 ; [02] режим открытия
SFT_B_DirAttrib DB 0 ; [04]
- 4-20 -
SFT_W_Flags DW 0 ; [05]
SFT_D_DCB DD 0 ; [07] (FILE) блок управления устройством
SFT_W_Cluster1 DW 0 ; [0b] (FILE) начальный кластер
SFT_W_HHMMS DW 0 ; [0d] (FILE) часы, минуты, секунды
SFT_W_YYMMDD DW 0 ; [0f] (FILE) год, месяц, день
SFT_D_FilSiz DD 0 ; [11] размер файла/размещение EOF
SFT_D_FilPos DD 0 ; [15] текущая позиция файла
SFT_W_RelClstr DW 0 ; [19] (FILE) начало кластеров
SFT_W_CurClstr DW 0 ; [1b] (FILE) текущий кластер
SFT_W_LBN DW 0 ; [1d] (FILE) номер блока
SFT_W_DirIndex DB 0 ; [1f] (FILE) индекс каталога
SFT_T_FileName DB 0bh DUP (0) ; [20] (FILE) имя файла
SFT_T_Unknown DB 04h DUP (0) ; [2b] неизвестно
SFT_W_OwnerMach DW 0 ; [2f] номер машины владельца файла
SFT_W_OwnerPSP DW 0 ; [31] PSP задачи, которая начинается
SFT_W_Status DW 0 ; [33]
SFT ENDS
SFT_K_Size EQU SIZE SFT
;
;MOde field
;
SFT_M_FCB EQU 8000h ; вход для FCB
SFT_M_DenyNone EQU 0040h ; разделяемые биты (4-6)
SFT_M_DenyRead EQU 0030h ; "
SFT_M_DenyWrite EQU 0020h ; "
SFT_M_Exclusive EQU 0010h ; "
SFT_M_NetFCB EQU 0070h ; это сетевой FCB
SFT_M_Write EQU 0001h ; биты доступа к файлу
SFT_M_Read EQU 0000h ; "
;
;Flags Field
;
SFT_M_Shared EQU 8000h ; сетевой доступ
SFT_M_DateSet EQU 4000h ; набор данных (только для FILE)
SFT_M_IOCTL EQU 4000h ; поддержка IOCTL (только для DEVICE)
SFT_M_IsDevice EQU 0080h ; вход для устройства
SFT_M_EOF EQU 0040h ; (DEVICE) конец ввода файла
SFT_M_Binary EQU 0020h ; (DEVICE) прозрачный режим
SFT_M_Special EQU 0010h ; (DEVICE) поддерживает вывод int 29h
SFT_M_IsClock EQU 0008h ; (DEVICE) устройство текущего времени
SFT_M_IsNul EQU 0004h ; (DEVICE) текущее фиктивное устройство
SFT_M_IsStdOut EQU 0002h ; (DEVICE) текущее устройство вывода
SFT_M_IsStdIn EQU 0001h ; (DEVICE) текущее устройство входа