最近有点忙,一直没有时间来总结一下,好不容易逮着个有时间的星期天,静下心来,好好总结一下,完成未完成的系列教程,好了,废话少说,开题了。
现在进行Windows驱动开发,主要有两种框架,一种是NT框架的驱动,一种是WDM框架的驱动程序,微软后来为了区分WDM驱动的,又推出了KMDF和UMDF两种框架,KMDF是针对内核态的驱动程序开发的框架,而UMDF是用户态的驱动程序的开发框架,这两个框架对底层的API的封装程度又加重了一点,对于底层的安全软件的开发降低了控制的程度,就像微过滤驱动一样,不少安全厂商并不买账。
NT驱动主要工作在Windows 2000下,不支持即插即用和电源管理,大概包括三部分:入口函数(DriverEntry)、卸载历程(DriverUnload)、分发例程(Dispatch Function)。下面分别讲述这三个部分。
入口函数(DriverEntry)
驱动的入口函数主要是对驱动程序进行初始化工作,它是由系统进程所调用。在驱动程序初始化的时候,入口函数被加载进内存,进行初始化,完成之后,就要退出内存。一般入口函数的前边都要有这么一个标记
#pragma code_seg("INIT")标记驱动入口函数在内存中的位置。NT驱动的入口函数一般完成的工作也很简单,就是注册分发例程,下面是一个简单的代码示例:
卸载例程(DriverUnload)
卸载例程,顾名思义,就是负责驱动程序的卸载的。完成清扫的工作,删除符号链接,删除设备对象等等,下面是示例代码:
分发例程Dispatch
分发例程是驱动中真正进行功能实现的部分,系统产生的IRP都是由该部分进行处理,并且在执行的时候,分发函数运行在不同的进程中,存在于分页内存中,最最简单的处理函数可以参考上一篇文章中的示例代码,只是实现了转交的作用,具体想实现的功能,就要看用户的不同需求了,这里就不再赘述。
创建设备对象的函数代码:
在Windows 2000出现之后,微软又加入了新的驱动模型--WDM驱动模型,主要添加了对即插即用和电源管理的支持。驱动的大概结构和NT驱动很类似,新增了添加设备例程,类似于上面的CreateDevice函数,因为在NT驱动中,不少开发者直接把CreateDevice的实现放在了DriverEntry中了,而我只是把它单拿出来了。
入口函数(DriverEntry)
WDM驱动程序的入口函数和上面的差不多,通用的代码中加入下边一句话就行了:
添加设备例程(AddDevice)
AddDevice类似于NT驱动中DriverEntry创建设备对象函数,但是略有不同,参数的个数不同,DriverObject是I/O管理器创建的驱动对象,PhysicalDeviceObject是底层总线驱动创建的PDO对象。大概的步骤是这样的:
首先通过IoCreateDevice创建设备对象,然后保存设备对象的地址,接下来将创建的设备对象FDO附加在底层PDO上面,最后设置FDO的flags子域。示例代码:
分发例程(Dispatch Function)
通用的分发例程就不在介绍了,跟上面NT驱动的一样,没什么区别,下面介绍一下PNP。
即插即用例程Pnp
即插即用IRP,即IRP_MJ_PNP,一般是由即插即用管理器发送给WDM驱动程序的。关于即插即用,用户可以查看更加详细的资料,这里主要讲述一个IRP的处理,对IRP_MN_REMOVE_DEVICE IRP进行处理,这个例程主要实现了原来DriverUnload所实现的功能。原理很简单,看一下示例代码:
卸载历程(DriverUnload)
卸载例程现在显得可有可无了,给一个简单的示例吧,其实什么都没实现
这一点就说到这吧,本来还想说说驱动栈的结构,因为需要用图表比较清晰,现在无法上传图片,就不讲了。