WDM引入了设备对象的概念来描述设备,它主要包括物理设备对象(PDO),功能设备对象(FDO)和过滤设备对象(FIDO)。其中,PDO对应于实际的物理设备,FDO和过滤器DO是相应驱动程序的处理对象。一台物理设备只能有一个PDO和一个FDO,但它可以有多个过滤器DO。 WDM驱动程序直接操作的不是硬件本身,而是相应的PDO,FDO和过滤器DO。当用户发送请求时,操作系统会将其打包以形成IRP结构并将其发送给驱动程序,并通过在IRP中标识设备对象来区分将其发送给哪个设备。 WDM驱动程序采用分层的驱动方法,即用户应用程序和硬件设备之间有几种不同的驱动程序,每个驱动程序对应一个层,并且不同层上的驱动程序可以相互调用。下面详细说明驱动程序的类型:为了适合即插即用系统,WDM重新定义了驱动程序的层次结构,主要包括以下3种类型的驱动程序。
(1)总线驱动程序:负责驱动I / O总线,处理总线上的所有事务并控制对总线上所有设备的访问。计算机上的每种总线类型都需要一个总线驱动程序,即如果每台计算机包含多条相同类型的总线,则只有一个总线驱动程序可以同时驱动它们。
(2)功能驱动程序:用于驱动单个设备,控制和实现设备的主要功能,它是设备的主要驱动程序,也是必不可少的。对于设备,最多为PnP管理器只能为其加载一个功能驱动程序,但是一个功能驱动程序可以同时为多个设备提供服务。
(3)筛选器驱动程序:用于筛选发送到设备,设备类或总线的I / O请求。它是可选的,即设备可以具有零个或多个筛选器驱动程序。筛选器驱动程序可以提供服务多个设备对象同时存在,并且可以进一步分为总线过滤器驱动器,上层过滤器驱动器和下层过滤器驱动器,设备通常需要使用一个总线驱动器,一个功能驱动器以及零个或多个过滤器驱动程序,其中一些是由操作系统提供的,有些需要由开发人员编写的,具体取决于特定的设备WDM驱动程序是系统内核模式驱动程序,可以执行任何有效的CPU指令,尤其是I / O操作:内核模式的其他组件通过发送I / O请求在WDM驱动程序中运行代码。这些I / O请求负责指定驱动程序应完成的特定操作。
WDM驱动程序组成:简而言之,驱动程序是例程的集合,这些例程被动存在,等待主机系统软件(即插即用管理器,I / O管理器,电源管理器等)调用或激活它们。特定的驱动程序不同,并且所包含的例程也不同。 WDM驱动程序至少包括5个例程:
(1)驱动程序入口例程:处理驱动程序的初始化。
([2)即插即用例程:处理PnP设备的添加,删除和停止。
([3)分发例程:处理用户应用程序发出的各种I / O请求。
([4)电源管理例程:处理电源管理请求。
([5)卸载例程:处理驱动程序的卸载。
1。驾驶员进入程序
DriverEntry例程是驱动程序的入口点,在加载驱动程序时由I / O管理器调用。它负责执行一些初始化操作,其主要工作是在驱动程序对象(DriverObject)中设置指向各种例程的指针。这些例程的特定功能实现必须包含在驱动程序中,以供主机系统软件调用。
NTSTATUS DriverEntry(在PDRIVER_OBJECT DriverObject中,
在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;
返回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->接口= NULL;
///设置读写请求以使用直接I / O
fdo->标志&=〜DO_DEVICE_INITIALIZING;
fdo->标志| = 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;
开关(MinorFunction)
{
案例IRP_MN_START_DEVICE:
//资源分配
ntStatus = PnpHandleStartDevice(fdo,Irp);
休息;
IRP_MN_STOP_DEVICE:
//首先将IRP向下传递
PnpHandleDefault(fdo,Irp);
ntStatus = PnpHandleStopDevice(fdo);
休息;
案例IRP_MN_REMOVE_DEVICE:
//删除设备
ntStatus = PnpHandleRemoveDevice(fdo,Irp);
休息;
默认值:
//向下传递所有其他PnP IRP
ntStatus = PnpHandleDefault(fdo,Irp);
}
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-368810-1.html
期待