Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
SP_MET_2.DOC
Скачиваний:
13
Добавлен:
02.05.2019
Размер:
689.66 Кб
Скачать

2.5.Драйверы устройств в dos

Прикладные программы обращаются ко всем устройствам с помощью средств операционной системы. DOS, в свою очередь, обращается к средствам BIOS, которые осуществляют взаимодействие на уровне портов ввода-вывода со всеми стандартными устройствами. Фактически процедуры BIOS выполня­ют функции драйверов устройств — программ, осуществляющих интер­фейс между операционной системой и аппаратной частью компьютера. Если, однако, требуется подключить к компьютеру новое устройство, поддержка которого в BIOS отсутствует, появляется необхо­димость в специально написанном загружаемом драйвере.

Драйверы устройств в DOS — исполнимые файлы со специальной структурой, которые загружаются на этапе запуска операционной системы.

DOS поддерживает два типа драйверов: символьные и блочные. Блочные драйверы используются для устройств, на которых могут существовать файловые системы, то есть для дисководов, RAM-дисков, нестандарт­ных жестких дисков, для доступа к разделам диска, занятым другими операционными системами, и т. д., а символьные — для всех остальных устройств, например, клавиатуры, принтера, сети. Чтобы обратиться к символьному ус­тройству, программа должна открыть его при помощи функции DOS «открыть файл или устройство», а чтобы обратиться к блочному устрой­ству — просто обратиться к соответствующему логическому диску.

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

Встроенные в ядро DOS драйверы загружаются из интерфейсного файла IO.SYS (или эквивалентного ему), а внешние устанавливаемые драйверы — из других файлов (обычно также с расширением .SYS) при выполнении команд DEVICE или DEVICEHIGH конфигурационного файла CONFIG.SYS. Будучи установленными, драйверы становятся фактически частью системы.

Установка драйверов при старте системы происходит следующим образом. Как только интерфейсный файл IO.SYS оказывается загруженным в память, управление передается содержащейся в нем процедуре инициализации. Сама процедура инициализации заключается в распределении частей DOS в памяти, создании всех внутренних таблиц, рабочих областей и, наконец, инициализации всех стандартных устройств, связанных с системой. Инициализация устройств заключается в посылке команды INIT каждому из стандартных драйверов, содержащихся в интерфейсном файле (команда INIT рассматривается далее, вместе с другими командами для драйверов устройств). После инициализации устройств процедура инициализации заканчивает создание внутренних таблиц и проверяет наличие файла CONFIG.SYS. Если указанный файл отсутствует, то DOS загружает командный процессор и передает ему управление. Если же файл CONFIG.SYS найден, то выполняется его обработка, в частности, подключение к DOS пользовательских драйверов устройств.

Подключение внешних драйверов выполняется с помощью команды DEVICE или ее более познего аналога DEVICEHIGH файла CONFIG.SYS. Команда имеет следующий формат (заключенные в квадратные скобки элементы не являются обязательными):

DEVICE=[d:][path]filename[.ext][parameters]

где d: — идентификатор логического диска;

path — путь к драйверу;

filename — имя файла, содержащего драйвер,

ext — расширение имени файла,

parameters — параметры для драйвера.

Когда в файле CONFIG.SYS встречается команда DEVICE, соответствующий драйвер загружается в память и анализируется. Драйвер всегда начинается с заголовка, содержащего информацию о типе, имени, атрибутах устройства и определяющего точки входа в программу. После загрузки драйвера DOS обращается к драйверу с командой INIT. Драйвер выполняет инициализацию и возвращает управление DOS, указывая адрес конца драйвера, т. е. адрес первого свободного байта памяти, непосредственно следующего за драйвером. На этом установка драйвера заканчивается.

Указание адреса конца драйвера после выполнения команды INIT подобно указанию размера памяти, занимаемой резидентной программой, при вызове функции DOS "Оставить программу резидентной". По возвращаемому адресу DOS определяет расположение свободной памяти. Если файл CONFIG.SYS содержит другие команды DEVICE, следующий драйвер загружается непосредственно после предыдущего. После того, как обработка файла CONFIG.SYS закончена, загружается еще один драйвер — драйвер фиктивного устройства (NUL-драйвер). Затем DOS завершает инициализацию загрузкой постоянной части командного процессора COMMAND.COM (или его аналога).

При загрузке драйверов DOS связывает их в цепочку так, чтобы каждый из них содержал ссылку на ранее загруженный драйвер. Цепочка драйверов начинается, таким образом, с последнего загруженного драйвера (NUL-драйвер) и заканчивается самым первым загруженным драйвером (обычно стандартный драйвер устройства COM2). Такая цепочка строится с использованием первых двух слов заголовка каждого драйвера. Эти два слова содержат сегмент и смещение следующего в цепочке драйвера или, в случае последнего драйвера, число –1 (FFFFh).

Когда DOS необходимо обратиться к определенному драйверу, она начинает поиск по цепочке драйверов (начиная с NUL-драйвера) в порядке, обратном тому, в котором драйверы были загружены. После того, как требуемый драйвер найден, DOS обращается к нему с соответствующей командой. Последовательность поиска в цепочке при этом такова, что если загружен пользовательский драйвер, имя которого совпадает с именем какого-либо стандартного драйвера (такого как CON, AUX или PRN), драйвер пользователя будет найден первым. Это позволяет пользователю заменять стандартные драйверы (например, заменить стандартный CON-драйвер на ANSI.SYS).

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

Поскольку стандартные драйверы загружаются и инициализируются до обработки файла CONFIG.SYS, их инициализационные секции могут использовать некоторые функции DOS для вывода сообщений или настройки драйвера на конкретную версию операционной системы. Например, для драйверов, обеспечивающих работу с устройствами CON, PRN и AUX, могут быть использованы функции DOS с 01h по 0Ch, а также функция 30h ("Получить версию DOS"). Вызовов, относящихся к работе с файлами или управлением памятью, следует избегать, так как распределение памяти к этому моменту еще не завершено.

Базовая структура драйвера устройства включает три раздела — заголовок драйвера, процедура стратегии и процедура прерывания. Заголовок драйвера имеет следующий формат:

+00: 4 байта: дальний адрес следующего загружаемого драйвера DOS — так как в момент загрузки драйвер будет последним в цепоч­ке, адрес должен быть равен FFFFh:FFFFh (–1)

+04: 2 байта: атрибуты драйвера

+06: 2 байта: адрес процедуры стратегии

+08: 2 байта: адрес процедуры прерывания

+0Ah: 8 байт: имя драйвера для символьных устройств (дополненное пробелами); для блочных устройств байт по смещению 0Аh содержит число устройств, поддерживаемых этим драйвером, а остальные байты могут содержать имя драйвера

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

+00h: байт — длина буфера запроса (включая заголовок)

+01h: байт — номер устройства (для блочных устройств)

+02h: байт — код команды (00h - 19h)

+03h: 2 байта — слово состояния драйвера — должно быть заполнено драйвером:

бит 15: произошла ошибка

биты 10 - 14: 00000b

бит 9: устройство занято

бит 8: команда обслужена

биты 7-0: код ошибки: 00h: устройство защищено от записи; 01h: неизвестное устройство; 02h: устройство не готово; 03h: неизвестная команда; 04h: ошибка CRC; 05h: ошибка в буфере запроса; 06h: ошибка поиска; 07h: неизвестный носитель; 08h: сектор не найден; 09h: нет бумаги; 0Аh: общая ошибка записи; 0Bh: общая ошибка чтения; 0Сh: общая ошибка; 0Fh: неожиданная смена диска

+05h: 8 байт зарезервировано

+0Dh: отсюда начинается область данных, различающаяся для разных команд

Даже если драйвер не поддерживает запрошенную от него функцию, он обязательно должен установить бит 8 слова состояния в 1.

Ниже представлен общий каркас драйвера устройства на ассемблере. Хотя структура драйвера похожа на структуру .COM программы, важно отметить следующие отличия: программа начинается с нулевого смещения, а не 100h, так как не нужно резервировать место для PSP; образ программы начинается с директив определения данных для заголовка драйвера; программа не содержит директивы ASSUME для стекового сегмента; программа не содержит директивы END <точка_входа>.

driver segment para

assume cs:driver, ds:nothing, es:nothing

org 0

start: ; начало драйвера

; заголовок драйвера

dd -1 ; указатель на следующий драйвер

dw attribute ; слово атрибутов

dw offset strategy ; точка входа в процедуру strategy

dw offset interrupt ; точка входа в процедуру interrupt

db 8 dup (?) ; количество устройств / поле имени устройства

; резидентная часть драйвера

req_ptr dd ? ; указатель на заголовок запроса

[. . .]

; процедура стратегии

; на входе адрес заголовка запроса находится в регистрах es:bx

strategy proc far

mov cs:word ptr [req_ptr], bx ; сохранить адрес заголовка запроса

mov cs:word ptr [req_ptr + 2], es ; для процедуры стратегии

ret

strategy endp

; процедура прерываний

; обработать команду, находящуюся в заголовке запроса

interrupt proc far

pusha ; сохранить все регистры

lds bx, cs:[req_ptr] ; получить адрес заголовка запроса

[. . .]

interrupt endp

[. . .]

driver ends

end

Каркас дает общее представление о структуре исходного текста драйвера. Для создания же рабочего драйвера необходима по меньшей мере подробная информация о командах, передаваемых драйверам, и форматах буферов запросов, которые различны для символьных и блочных устройств. Возможно, также потребуется описание подфункций функции управления вводом-выводом IOCTL (функция 44h DOS), которая часто используется при создании драйверов. Эти сведения содержатся в справочных руководствах по DOS. Конкретные примеры реальных драйверов можно найти в [1] и [7].

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]