РуЛиб - онлайн библиотека > Гром > Системное программирование > Как писать драйвера > страница 2

Читаем онлайн «Как писать драйвера» 2 cтраница

среднестатистическую структуру драйвера.

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

В каждом драйвере есть входная точка, соответствующая функции main(), в замечательном С, WinMain() в Windows. Функция вызывается при старте системы автоматически в момент инициализации обслуживающей части Windows к которой относится данный драйвер.

Функции выхода нет.

Еще чуть-чуть лирики. В нашей с вами ситуации дистанционного общения, придется брать и писать один из драйверов для примера. Без этого будет сложновато объяснить, что мы делаем и зачем. Поэтому я предлагаю выбрать некий тип для нашего примера.

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

Отбросив таким образом драйвера, который привязаны к железке мы остановимся на типе Network – сетевых драйверах.

Сетевые драйвера.
Сетевые драйвера тоже как и драйвера типа kernel, делятся на такие же три уровня. Вспомните, что все разделение я назвал условным.

Меняется только название.

– Miniport drivers;

– Protocol drivers;

– Intermediate drivers.

Структура сетевой части драйверного поголовья, похожа на пирог. Давайте посмотрим как это выглядит.

«Как писать драйвера» картинка № 2
На рисунке четко видно, как структура NDIS (Network Driver Interface Specification) пронизывает все слои драйверного пирога.

Теперь давайте представим как проходит пакет от пользовательской аппликации к посылке через модем или сетевую карту в сеть. Все клиенты Microsoft, такие как браузер IE, или Outlook, пользуются одним и тем же слоем библиотек, откликающихся на имя транспортные библиотеки.

Главным в этом семействе является библиотека сокетов. Про то как она работает вы прочитаете в наших выпусках посвященных Winsock. В любом случае библиотека, оформив запрос отправляет его в NDIS, и о нем совершенно забывает. В структуре нашего пирога, главным управляющим звеном является как раз NDIS. Этот цербер распределяет кому и как передать пакет. Собственно драйвер в сети встроенный в NDIS предоставляет управленцу все необходимые прототипы функций. Начав с первого типа, протокольного, пакет проходит через слой промежуточных драйверов и попадает в драйвер модема (Miniport – это слово я на русский затруднился перевести в контексте, пусть так и останется).

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

Для нас важно, что промежуточный драйвер не привязан ни к оборудованию, ни к какому либо стандарту Windows, но соответствует своей структурой любому сетевому драйверу.

Поэтому в качестве примера мы выберем именно его.

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

Как писать драйвера (часть 3)

Структура драйвера.

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

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

Для тех, кому тяжело качать Win2000 DDK размером 41Мб мы выложили базисный код драйвера в архиве. Скачайте архив для более полного ознакомления с текстом и работы с нашим текстом.

Сама DriverEntry запускается один раз, но важность правильной регистрации, думаю, понятна всем. Рассмотрим ее текст полностью.

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)

/*++

 Routine Description:

 Arguments:

 Return Value:

--*/

{

 NDIS_STATUS Status;

 NDIS_PROTOCOL_CHARACTERISTICS PChars;

 NDIS_MINIPORT_CHARACTERISTICS MChars;

 PNDIS_CONFIGURATION_PARAMETER Param;

 NDIS_STRING Name;

 NDIS_HANDLE WrapperHandle;

 //

 // Register the miniport with NDIS. Note that it is the miniport

 // which was started as a driver and not the protocol. Also the miniport

 // must be registered prior to the protocol since the protocol's BindAdapter

 // handler can be initiated anytime and when it is, it must be ready to

 // start driver instances.

 //

 NdisMInitializeWrapper(&WrapperHandle, DriverObject, RegistryPath, NULL);

 NdisZeroMemory(&MChars, sizeof(NDIS_MINIPORT_CHARACTERISTICS));

 MChars.MajorNdisVersion = 4;

 MChars.MinorNdisVersion = 0;

 MChars.InitializeHandler = MPInitialize;

 MChars.QueryInformationHandler = MPQueryInformation;

 MChars.SetInformationHandler = MPSetInformation;

 MChars.ResetHandler = MPReset;

 MChars.TransferDataHandler = MPTransferData;

 MChars.HaltHandler = MPHalt;

 //

 // We will disable the check for hang timeout so we do not

 // need a check for hang handler!

 //

 MChars.CheckForHangHandler = NULL;

 MChars.SendHandler = MPSend;

 MChars.ReturnPacketHandler = MPReturnPacket;

 //

 // Either the Send or the SendPackets handler should be specified.

 // If SendPackets handler is