Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15317011
  • 博文数量: 2005
  • 博客积分: 11986
  • 博客等级: 上将
  • 技术积分: 22535
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-17 13:56
文章分类

全部博文(2005)

文章存档

2014年(2)

2013年(2)

2012年(16)

2011年(66)

2010年(368)

2009年(743)

2008年(491)

2007年(317)

分类:

2007-05-17 15:12:27

WDM 引入设备对象的概念来描述一个设备,主要包括物理设备对象(PDO)、功能设备对象(FDO)和过滤设备对象(FIDO)。其中,PDO 对应实际的物理设备,FDO filter DO时相应驱动程序的处理对象。一个物理设备有且只能有一个PDO 和一个FDO,但却可以有多个filter DOWDM 驱动程序直接操作的不是硬件本身,而是相应的PDOFDO filter DO。当用户发出请求时,操作系统会将其打包形成一个IRP结构,并把它发送至驱动程序,通过识别IRP 中的设备对象来区分它是发送给哪个设备的。WDM 驱动采用分层驱动的方法,即在用户应用程序和硬件设备之间存在着几个不同的驱动程序,每个驱动程序对应一层,且不同层上的驱动程序可以相互调用。下面详细讲解驱动程序种类:为适用于即插即用系统,WDM 新定义了驱动程序的分层结构,其主要包括如下3 中类型的驱动程序。

1)总线驱动程序:负责驱动I/O总线,处理总线上的全部事务,控制对其总线上所有设备的访问。计算机上每种类型的总线都需要有一个总线驱动程序,它是必不可少的。如果每台计算机上包含有多个同种类型总线,则其只需一个总线驱动程序就可以同时驱动它们。

2)功能驱动程序:用于驱动一个单独的设备,控制并实现该设备的主要功能,它是设备的主要驱动程序,也是必不可少的。对于一个设备,PnP管理器最多只能为其加载一个功能驱动程序,但一个功能驱动程序可以同时服务于多个设备。

3)过滤驱动程序:用于过滤发向设备、设备类或总线的I/O请求。它是可选的,即一个设备可以拥有零个或多个过滤驱动程序。一个过滤驱动程序可以同时服务于多个设备对象,其又可被进一步划分为总线过滤驱动程序、上层过滤驱动程序和下层过滤驱动程序。一个设备通常需要使用一个总线驱动程序、一个功能驱动程序、零个或多个过滤驱动程序。它们有的由操作系统提供,有的需要由开发人员自行编写,这根据具体设备的不同而不同。WDM 驱动程序是系统内核模式的驱动程序,它可以执行任何有效的CPU指令,尤其是I/O操作。内核模式的其他组件通过发送I/O请求的方式运行WDM 驱动程序中的代码,这些I/O 请求负责指明驱动程序应完成的具体操作。

WDM 驱动程序组成:简单地说,驱动程序是一些例程地集合,它们被动地存在,等待主机系统软件(PnP管理器、I/O管理器、电源管理器等)来调用或激活它们。具体驱动程序不同,其所包含的例程也不同,一个WDM驱动程序至少包括5 个例程:

1)驱动程序入口例程:处理驱动程序的初始化。

2)即插即用例程:处理PnP 设备的添加、删除和停止。

3)分发例程:处理用户应用程序发出的各种I/O 请求。

4)电源管理例程:处理电源管理请求。

5)卸载例程:处理驱动程序的卸载。

1驱动程序入口例程

DriverEntry 例程是驱动程序的入口点,由I/O管理器在驱动程序加载时调用。它负责执行一些初始化操作,主要工作是设置驱动对象(DriverObject)中指向各种例程的指针。在其驱动程序中必须包含这些例程的具体函数实现,以便主机系统软件的调用。

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,

IN PUNICODE_STRING RegistryPath)

{

NTSTATUS ntStatus = STATUS_SUCCESS;

DriverObject->DriverExtension->AddDevice = TestAddDevice;

DriverObject->MajorFunction[IRP_MJ_PNP] = TestPnpIrp;

DriverObject->MajorFunction[IRP_MJ_POWER] = TestPowerIrp;

DriverObject->MajorFunction[IRP_MJ_CREATE] = TestCreate;

DriverObject->MajorFunction[IRP_MJ_CLOSE] = TestClose;

DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = TestIOCTL;

DriverObject->DriverUnload = TestDrvUnload;

return ntStatus;

}

 

DriverEntry 为驱动程序的入口函数,它向操作系统注册“事件处理函数”

DriverObject->DriverExtension->AddDevice = TestAddDevice;

TestAddDevice为即插即用例程主要做如下工作:

实现设备对象的创建

//创建设备对象

ntStatus = IoCreateDevice (DriverObject,sizeof (DEVICE_EXTENSION),

&KernelDeviceNameUnicode,FILE_DEVICE_UNKNOWN,0,FALSE,&fdo);

实现符号链接名'Glx-gliet-05-05-25'的注册

//创建符号链接名

ntStatus = IoCreateSymbolicLink (&UserDeviceLinkUnicode,

&KernelDeviceNameUnicode);

DEVICE_EXTENSION 设备扩展初始化

//将符号链接名拷贝到自定义数据结构中-设备扩展中

RtlCopyMemory(pdx->DeviceLinkName,UserDeviceLinkBuffer,

sizeof(UserDeviceLinkBuffer));

pdx->OpenHandles = 0;

pdx->ConfigurationHandle = NULL;

pdx->DeviceDescriptor = NULL;

pdx->Interface = NULL;

//设置读写请求使用直接I/O

fdo->Flags &= ~DO_DEVICE_INITIALIZING;

fdo->Flags |= DO_DIRECT_IO;

//将物理设备对象保存到设备扩展中

pdx->PhysicalDeviceObject=PhysicalDeviceObject;

挂接到设备栈

//把设备对象连接到设备栈

pdx->LowerDeviceObject =IoAttachDeviceToDeviceStack(fdo,

PhysicalDeviceObject);

初始化事件

//初始化一个内核事件

KeInitializeEvent(&pdx->evRemove,NotificationEvent,FALSE);

DriverObject->MajorFunction[IRP_MJ_PNP] = TestPnpIrp;

TestPnpIrp 为即插即用例程主要做如下工作:

//完成大部分初始化工作

MinorFunction = IrpStack->MinorFunction;

switch (MinorFunction)

{

case IRP_MN_START_DEVICE:

//进行资源分配

ntStatus = PnpHandleStartDevice(fdo,Irp);

break;

case IRP_MN_STOP_DEVICE:

//首先向下传递该IRP

PnpHandleDefault(fdo,Irp);

ntStatus = PnpHandleStopDevice(fdo);

break;

case IRP_MN_REMOVE_DEVICE:

//删除设备

ntStatus = PnpHandleRemoveDevice(fdo,Irp);

break;

default:

//向下传递所有其他PnP IRP

ntStatus = PnpHandleDefault(fdo, Irp);

}


阅读(6237) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~