Операционная система Microsoft Windows 3.1 для программиста. Дополнительные главы© Александр Фролов, Григорий ФроловТом 17, М.: Диалог-МИФИ, 1994, 287 стр. 5. Драйверы для Windows
В этой главе мы затронем одну из сложнейших областей программирования для операционной системы Windows - создание драйверов. Традиционно считается, что разработка драйвера для Windows доступна лишь немногим программистам, и отчасти это так и есть. Особенно если речь заходит о драйвере для видеоадаптера, принтера или другого стандартного оборудования компьютера. Если вы сомневаетесь - посмотрите исходные тексты драйверов, которые есть в составе DDK. Они содержат тысячи строк ассемблерного "бреда"! Посмотрев на все это, вы, возможно, с тоской вспомните старые времена, когда казалось, что драйверы для MS-DOS - это очень сложные программы, которые не так просто составить и отладить. В чем же сложность? Только ли в объеме листингов? Увы, нет. Для начала сообщим, что в операционной системе Windows существуют драйверы трех типов. Причем два их них используются как в стандартном, так и в расширенном режиме работы Windows, а один - только в расширенном (к счастью, реальный режим Windows ушел в прошлое, вслед за ним идет и стандартный: Windows for Workgroups версии 3.11 работает только в расширенном режиме). Драйверы первого типа (мы будем называть их стандартными драйверами) представляют собой обычные DLL-библиотеки и обслуживают стандартные устройства компьютера "с первых дней жизни" Windows. Когда-то, когда Windows еще не работал в расширенном режиме, это был единственный тип драйверов. Стандартные драйверы, как и полагается драйверам, в стандартном режиме Windows работают непосредственно с регистрами аппаратуры (кроме драйвера принтера). Соответствующие DLL-библиотеки экспортируют функции, доступные как ядру Windows, так и обычным приложениям. Несмотря на то, что мы называем эти драйверы стандартными, не существует никакого стандартного набора экспортируемых такими драйверами функций. Так как устройства компьютера достаточно сильно отличаются друг от друга, сложно придумать единый интерфейс, удовлетворяющий требованиям, например, таких разных устройств, как дисплейный адаптер и принтерный порт. Поэтому можно считать, что стандартные драйверы для стандартных устройств компьютера - это программы с разнотипным интерфейсом, которые объединяет только то, что все они реализованы как DLL-библиотеки, что приложения вызывают их для доступа к аппаратуре, и что все они загружаются в память в процессе загрузки Windows. С возникновением версии 3.0 операционной системы Windows на свет появился новый тип драйверов - виртуальные драйверы. Виртуальные драйверы не похожи ни на что другое в Windows. Это 32-разрядные DLL-библиотеки, работающие в так называемой FLAT-модели памяти. Они - чужестранцы в 16-разрядном мире Windows версий 3.0 и 3.1. FLAT-модель является сплошной (несегментированной) моделью памяти. Однако название модели памяти не должно вводить вас в заблуждение. На самом деле сегменты памяти существуют всегда (так как даже в процессоре Pentium есть сегментные регистры!), но размер этих сегментов для FLAT-модели составляет 4 Гбайт. Базовый адрес гигантских сегментов, адресуемых виртуальными драйверами, равен нулю, т. е. соответствует началу памяти. В результате этого, а также из-за того, что виртуальные драйверы работают в нулевом кольце защиты, они могут адресовать любой участок физической или виртуальной памяти системы. В частности, они имеют доступ к памяти любой запущенной виртуальной машины. Основное назначение виртуальных драйверов - обеспечение безконфликтного коллективного доступа к физической аппаратуре для всех одновременно работающих виртуальных машин. Устройства компьютера как бы виртуализируются для каждой виртуальной машины (отсюда и название "виртуальные драйверы"). Другая задача, решаемая виртуальными драйверами, заключается в организации взаимодействия между виртуальными машинами MS-DOS и системной виртуальной машиной, в которой работают все приложения Windows. Когда операционная система Windows запущена в расширенном режиме, стандартные драйверы не обращаются напрямую к аппаратуре, как это происходит в стандартном режиме. Вместо этого они обмениваются данными с виртуальными устройствами, вызывая функции виртуальных драйверов. Так как виртуальные драйверы работают в нулевом кольце защиты, они имеют доступ к любым участкам памяти, к командам ввода/вывода в любые порты и к привилегированным машинным командам процессора (а также арифметического сопроцессора). Поэтому виртуальный драйвер, в отличие от обычного приложения Windows и стандартного драйвера, может сделать в системе все, что ему вздумается. К сожалению, для того чтобы создать виртуальный драйвер, придется вспомнить язык ассемблера. И это еще одна сложность, далеко не последняя. Когда мы рассказывали вам в первом томе "Библиотеки системного программиста" о драйверах MS-DOS, мы упоминали, что драйверу недоступно большинство функций MS-DOS. Виртуальные драйверы находятся в намного лучшем положении. Они могут пользоваться обширным набором функций, предоставляемых, как правило, системными виртуальными драйверами (сервисом виртуальных драйверов). Это сотни функций! И вы должны овладеть этим сервисом, или хотя бы основной его частью. Третий тип драйверов появился в Windows одновременно с системой мультимедиа. Это так называемые загружаемые драйверы. Загружаемые драйверы не представляют из себя ничего особенного - это простые DLL-библиотеки, экспортирующие среди прочих функцию DriverProc. Функция DriverProc используется для организации стандартизованного интерфейса, основанного на передаче сообщений. Загружаемые драйверы имеют также стандартный интерфейс для установки и конфигурирования. Как правило, в расширенном режиме работы Windows загружаемые драйверы не обращаются к аппаратуре непосредственно. Они вызывают для этого виртуальные драйверы. Например, вместе с широко известным звуковым адаптером Sound Blaster поставляется не только загружаемый, но и виртуальный драйвер. Безусловно, в одной книге, и тем более, в одной главе, невозможно привести всю информацию, необходимую для разработки драйверов перечисленных выше трех типов. Однако в этом нет необходимости. Что касается стандартных драйверов, то вы едва ли будете создавать их самостоятельно (если только вы не занимаетесь разработкой стандартной периферии компьютеров, такой как видеоконтроллеры или принтеры). В любом случае для разработки драйверов вам потребуется приобрести программный продукт Microsoft Driver Development Kit for Windows 3.1, содержащий полный комплект документации, примеры драйверов и все необходимые утилиты. Относительно подробное описание стандартных драйверов вы сможете также найти в книге "Writing Windows Device Drivers", написанной Д. Нортоном (имеется перевод этой книги на русский язык). Лучший способ создания собственного стандартного драйвера заключается в модификации исходного текста наиболее подходящего драйвера из комплекта примеров DDK. В нашей книге мы приведем только краткий обзор стандартных драйверов, уделив больше внимания виртуальным и загружаемым драйверам. Когда у вас может возникнуть необходимость создания собственного виртуального драйвера? Прежде всего, тогда, когда вам нужно использовать в расширенном режиме работы Windows нестандартное устройство ввода/вывода, работающее с прерываниями и каналами прямого доступа к памяти, особенно в реальном времени. Вам не обойтись без виртуального драйвера и в том случае, если ваше приложение Windows должно взаимодействовать с виртуальными машинами MS-DOS, резидентными программами и драйверами MS-DOS, загруженными до или после запуска Windows. Так как виртуальные драйверы имеют полный контроль над аппаратным обеспечением компьютера, с их помощью можно создавать эффективно работающие средства защиты от несанкционированного копирования программных продуктов. Приложения Windows могут использовать тот факт, что виртуальные драйверы работают в нулевом кольце защиты, для выполнения задач, не решаемых в рамках стандартного программного интерфейса Windows. Мы, разумеется, не призываем вас к созданию приложений, нарушающих защитный механизм Windows, однако иногда поставленную задачу невозможно решить иными способами. Для чего вам может потребоваться загружаемый драйвер? Загружаемый драйвер не имеет никаких привилегий перед обычными приложениями и DLL-библиотеками, однако для него предусмотрены стандартные методы инсталляции, конфигурирования и взаимодействия с приложениями. Это удобно для пользователя и программиста, поэтому в некоторых случаях, когда в паре с приложением необходимо использовать DLL-библиотеку, имеет смысл оформить последнюю в виде загружаемого драйвера. Ваше приложение может использовать загружаемый драйвер как интерфейс с виртуальным драйвером. При этом приложение взаимодействует с загружаемым драйвером с помощью механизма передачи сообщений, а вся работа по вызову виртуального драйвера возлагается на загружаемый драйвер. Так достигается полная функциональная независимость между приложением и драйверами: вы можете заменять версии драйверов на новые, не изменяя самого приложения. |