您的位置:首页 > 其它

Windows 驱动开发基础(七)WDM设备的基本结构

2014-08-25 20:25 841 查看
Windows 驱动开发基础系列,转载请标明出处:http://blog.csdn.net/ikerpeng/article/details/38822657

WDM驱动即是一种即插即用的驱动。

在WDM的结构中,一个设备对象有两部分组成:(1)物理设备对象PDO,(2)功能设备对象FDO。

当电脑上插上某个设备时,PDO会有总线驱动自动的创建。这个时候电脑也会提示安装驱动,这里需要安装的驱动就负责创建FDO并附加到PDO上面去。当一个FDO被附加到一个PDO上面的时候,就可以PDO的子域AttachedDevice就会记录FDO的位置。如下图所示:

                   


同时 FDO和PDO之间也存在着过滤驱动,同时这也构成了WDM型的驱动的分层结构!

                           


在WDM驱动里面也是包括了这几个方面:DriverEntry函数,AddDevice函数,DriverUnload函数以及对IRP_MN_REMOVE_DEVICE IRP。

DriverEntry:

extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,

IN PUNICODE_STRING pRegistryPath)

{

KdPrint(("Enter DriverEntry\n"));

//设置AddDevoce函数

pDriverObject->DriverExtension->AddDevice = HelloWDMAddDevice;

//设置各个IRP的派遣函数

pDriverObject->MajorFunction[IRP_MJ_PNP] = HelloWDMPnp;

pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =

pDriverObject->MajorFunction[IRP_MJ_CREATE] =

pDriverObject->MajorFunction[IRP_MJ_READ] =

pDriverObject->MajorFunction[IRP_MJ_WRITE] = HelloWDMDispatchRoutine;

//设置卸载例程

pDriverObject->DriverUnload = HelloWDMUnload;

KdPrint(("Leave DriverEntry\n"));

return STATUS_SUCCESS;

}


其中增加了对AddDevice函数的设置。因为WDM驱动是被动加载的,所以和NT不一样。但是创建设备对象已经不再这里了,而是在AddDevice里面。

AddDevice:

NTSTATUS HelloWDMAddDevice(IN PDRIVER_OBJECT DriverObject,

IN PDEVICE_OBJECT PhysicalDeviceObject)

{

PAGED_CODE();

KdPrint(("Enter HelloWDMAddDevice\n"));

NTSTATUS status;

PDEVICE_OBJECT fdo;

UNICODE_STRING devName;

RtlInitUnicodeString(&devName,L"\\Device\\MyWDMDevice");

/创建设备对象/

status = IoCreateDevice(

DriverObject,

sizeof(DEVICE_EXTENSION),

&(UNICODE_STRING)devName,

FILE_DEVICE_UNKNOWN,

0,

FALSE,

&fdo);

if( !NT_SUCCESS(status))

return status;

//      获取设备扩展结构

PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;

pdx->fdo = fdo;

//将FDO附加到PDO上,并且返回PDO对象

pdx->NextStackDevice = IoAttachDeviceToDeviceStack(fdo, PhysicalDeviceObject);

UNICODE_STRING symLinkName;

RtlInitUnicodeString(&symLinkName,L"\\DosDevices\\HelloWDM");

pdx->ustrDeviceName = devName;

pdx->ustrSymLinkName = symLinkName;

//创建符号链接

status= IoCreateSymbolicLink(&(UNICODE_STRING)symLinkName,&(UNICODE_STRING)devName);

if( !NT_SUCCESS(status))

{

IoDeleteSymbolicLink(&pdx->ustrSymLinkName);

status = IoCreateSymbolicLink(&symLinkName,&devName);

if( !NT_SUCCESS(status))

{

return status;

}

}

//设置设备标志

fdo->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;

fdo->Flags &= ~DO_DEVICE_INITIALIZING;

KdPrint(("Leave HelloWDMAddDevice\n"));

return STATUS_SUCCESS;

}


函数可以以任意命名,在AddDevice里面可以分为如下几步:

1.       在AddDevice中通过IoCreateDevice等函数,创建设备对象,该设备对象就是FDO。

2.       创建完FDO后,需要将FDO的地址保存下来,保存的位置就是在设备扩展中。

3.       驱动程序将创建的FDO附加到PDO上,依靠IoAttachDeviceToDeviceStack函数实现。附加以后,该函数返回附加设备的下层驱动。如果中间没有过滤驱动的话,返回的就是PDO,否则返回过滤驱动。

我们可以把该返回地址记录在设备扩展结构中,以此可以访问FDO的下层设备。

4.       设置FDO设备的Flags子域。DO_BUFFERED_IO是定义设备为“缓冲内存设备”,另外~DO_DEVICE_INITIALIZING,是将Flags上的DO_DEVICE_INITIALIZING位清零。保证设备初始化完毕,这一步是必须的。

DriverUnload:

主要负责收回申请的内存(卸载设备的操作在下一步)。

IRP_MN_REMOVE_DEVICE IRP:

IRP_MN_REMOVE_DEVICE这个IRP是当设备需要被卸载的时候,由即插即用管理器创建,并发送到驱动程序中。IRP一般有两个号码指定该IRP的具体意义。一个是主版本号(Major IRP),另一个是辅IRP号(Minor IRP).

当设备被卸载的时候,会先后发送多个IRP_MJ_PNP。这些IRP的辅IRP号会有所不同。其中之一就是IRP_MN_REMOVE_DEVICE.

在WDM驱动程序中,对设备的卸载一般都是在IRP_MN_REMOVE_DEVICE的处理函数中进行卸载。

例如:

NTSTATUS HandleRemoveDevice(PDEVICE_EXTENSION pdx, PIRP Irp)
{
PAGED_CODE();
KdPrint(("Enter HandleRemoveDevice\n"));
//设置IRP的完成状态
Irp->IoStatus.Status = STATUS_SUCCESS;
//将IRP请求向底层驱动转发
NTSTATUS status = DefaultPnpHandler(pdx, Irp);
//删除符号链接
IoDeleteSymbolicLink(&(UNICODE_STRING)pdx->ustrSymLinkName);

//调用IoDetachDevice()把fdo从设备栈中脱开:
if (pdx->NextStackDevice)
IoDetachDevice(pdx->NextStackDevice);
//删除fdo:
IoDeleteDevice(pdx->fdo);
KdPrint(("Leave HandleRemoveDevice\n"));
return status;
}


在处理IRP_MN_REMOVE_DEVICE的函数中,它的功能类似于NT驱动中的DriverUnload函数。除了删除设备,取消符号链接外,此函数中还需要将FDO从PDO上的堆栈中摘除下来。使用IoDetachDevice:

VOID 

IoDetachDevice(


IN OUT PDEVICE_OBJECT  TargetDevice

);


TargetDevice: 此时,FDO从设备链上被删除,但是PDO还是存在的。PDO的删除不是由程序员负责,而是由操作系统负责。

参考文献:

《 Windows 驱动开发技术详解 》

  http://mzf2008.blog.163.com/blog/static/35599786201011973648864/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  windows 7 驱动开发