文件系统驱动编程基本篇之2——尺度模子
当前位置:以往代写 > C/C++ 教程 >文件系统驱动编程基本篇之2——尺度模子
2019-06-13

文件系统驱动编程基本篇之2——尺度模子

文件系统驱动编程基本篇之2——尺度模子

副标题#e#

二、尺度模子

WDM回收了布局化的编程方法,执行效率很高,但编写效率较低,这也是DriverStudio得以成长的重要原因。正如把握了COM道理,利用ATL才气把握精华的原理一样,读者需要忍受影象大量基本常识的“疾苦”,临时放弃编写驱动措施的捷径。

下面的某些图示稍显陈旧,不外已经足以说明问题了。

文件系统驱动编程根基篇之2——标准模型
文件系统驱动编程根基篇之2——标准模型

尽量驱动措施分为多个种类(图1-4),但它们包括的根基内容(图1-5)是一致的。每个驱动措施都从初始化措施DriverEntry进入,通过某个调派例程DispatchXXX派发特定数令(我们不妨称之为IRP),这些IRP有大概在调派例程里就获得了办理,也有大概交给驱动措施的其他部门办理。假如驱动措施A自己不能处理惩罚这个IRP呼吁,它就需要将IRP通报到更基层的驱动B,由它们来处理惩罚,此时驱动措施A大概因为期待IRP完成而处于睡眠状态,或继承处理惩罚新的IRP,直到基层驱动B通知(或通过某种机制叫醒并通知)A该IRP已经处理惩罚完毕了,此时A就将处理惩罚的功效(我们称之为NTSTATUS)返回本来派发这个IRP的提倡人。这就是驱动措施处理惩罚IRP的一个简化进程。

我们提到了驱动措施是分层的这个观念,那么如何领略分层的观念呢?请看图示:

文件系统驱动编程根基篇之2——标准模型

引用资料1的原话:WDM模子利用了如图2-1的条理布局。图中左边是一个设备工具仓库。设备工具是系统为辅佐软件打点硬件而建设的数据布局。一个物理硬件可以有多个这样的数据布局。处于仓库最底层的设备工具称为物理设备工具(physical device object),或简称为PDO。在设备工具仓库的中间某处有一个工具称为成果设备工具(functional device object),或简称FDO。在FDO的上面和下面还会有一些过滤器设备工具(filter device object)。位于FDO上面的过滤器设备工具称为上层过滤器,位于FDO下面(但仍在PDO之上)的过滤器设备工具称为基层过滤器。

由某个家伙(大概是用户模式下的应用措施,也大概是系统内核组件)提倡的IRP从上层过滤器驱动措施一直顺流而下,通报到总线驱动措施处理惩罚后,再逐级返回上层,最终提倡人得处处理惩罚的功效。

一般环境下,IRP也许不需要通报到总线驱动措施就被处理惩罚掉了,但假如各人都不认识这个IRP,他们就只好逐级下传了,假如此时有个搞粉碎的驱动措施混了进来,拦截了这个IRP,轻则丢失用户信息、重启、死机,重则造成系统区的数据杂乱,你除了从头安装操纵系统再无任何工作可做。由此可见,我们不要求驱动措施“有抱负”,但必需“有规律”,每个驱动措施都必需严格凭据类型书写代码,这要求编程人员具备较高的素质。

下面我们来相识驱动编程里最根基的尺度模子,这个模子不能办理所有的编程需求,按照需要,它将存在各类变革。我们来看看这个驱动编程里的“根基定式”:

文件系统驱动编程根基篇之2——标准模型

IO打点器,各人应该领略为该IRP的提倡人,大概是张三,也大概是李四,而不是某个牢靠的组件。这个模子表白了单个驱动措施里各部件的相助与分工,留意它是个轮回不绝的进程,它的提倡人与最终接管人是沟通的,所谓“从那边来,就回那边去”。假如我们的编程不涉及真正的硬件,StartIo例程、间断处事例程ISR、DPC例程均大概不存在。各部件的详细成果请参看资料1的第五章。


#p#副标题#e#

三、根基例程、常用数据布局与函数

为正确领略种种例程的详细成果,需要弄清涉及的浩瀚内核函数、数据布局,读者应以本文和资料1为索引,当真的阅读Msdn上的相关内容。

我们的代码将从进口函数DriverEntry处开始执行,一般环境下,不要将它更名,不然需要修改DDK里的Build剧本。

驱动函数界说一般回收__stdcall约定,这个约定,在vs和bcb里的实际行为是差异的。如DriverEntry,两种编译器编译后的库中名字(即外部名字)别离是[email protected]和DriverEntry。我们还习惯以IN,OUT宏显式说明函数的参数是输入或输出参数。

DriverEntry里常见的几个例程由红字标出,包罗添加(硬件、虚拟)设备函数AddDevice、驱动卸载函数DriverUnload、StartIo函数以及安排于MajorFunction数组里的调派函数。DriverEntry还申请了分页池以生存注册表中的处事键,但作为文件系统驱动的DriverEntry,一般还会声明快速IO调派函数,这组调派函数没有呈此刻示例中。

#p#分页标题#e#

extern "C"
NTSTATUS
DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
DriverObject->DriverUnload = DriverUnload;         <--1
DriverObject->DriverExtension->AddDevice = AddDevice;
DriverObject->DriverStartIo = StartIo;
DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;         <--2
DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower;
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = DispatchWmi;
...         <--3
servkey.Buffer = (PWSTR) ExAllocatePool(PagedPool, RegistryPath->Length + sizeof(WCHAR)); <--4
if (!servkey.Buffer)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
servkey.MaximumLength = RegistryPath->Length + sizeof(WCHAR);
RtlCopyUnicodeString(&servkey, RegistryPath);
return STATUS_SUCCESS;         <--5
}

示例同时引用了多种数据布局,它们的具体注释可参看资料1第二章的第一小节的后半部门。我们首先把握这些数据布局的可见域,即可由编程人员存取的域,在领略一些重要的函数时也会涉及部门非透明域,一般环境下可利用微软推荐的函数来间接会见它们。

不要夹杂驱动工具和设备工具。驱动工具代表了内核加载的驱动镜像,DriverEntry或AddDevice例程挪用IoCreateDevice函数来建设设备工具时,驱动工具将作为该函数的一个输入参数。设备工具作为硬件或虚拟硬件的抽象,是一个极其重要的数据布局,用于处理惩罚设备的I/O请求。

我们将在WinDbg里实际查察这些数据布局,下面列出它们的界说图:

文件系统驱动编程根基篇之2——标准模型
文件系统驱动编程根基篇之2——标准模型
文件系统驱动编程根基篇之2——标准模型

#p#副标题#e#

内核函数按照执行的成果,大抵分为如下几类,读者可通过例子打仗到这些函数:

函数前缀 种别
Ex… 执行支持
Hal… 硬件抽象层(仅NT/Windows 2000/XP)
Io… I/O打点器(包罗即插即用函数)
Ke… 内核
Ks… 内核流IRP打点函数
Mm… 内存打点器
Ob… 工具打点器
Po… 电源打点(Vista下存在新的限制)
Ps… 历程布局
Rtl… 运行期库
Se… 安详
Zw… 其他函数
Cc… Cache函数
FsRtl… 文件系统运行期库

四、WinDbg上的实践

我们已在上一篇先容了如何用WinDbg查察KdPrint等内核函数输出的调试信息。事实上象vs或迅雷之类的软件也会发生调试信息,但它们由用户模式下的调试输出函数发出。

本次实践的工具是下篇将要用到的的示例代码,我们将演示如安在WinDbg里的常用操纵,如配置断点,查察变量的值、数据布局等,代码位于WINDDK\3790\src\general\ioctl。假如你还不会编译驱动措施,请赶紧完成上一篇拉下的功课。

用WinDbg毗连长途机,按g返还长途机的节制权,将编译好的驱动措施sioctl.sys和测试措施ioctlapp.exe复制到长途机上的任意目次里,如我们新建了一个目次c:\ioctl。

Ctrl+break返回WinDbg后,用.cls呼吁清屏,延时加载bu sioctl!DriverEntry,此时输入bl查察已经配置的断点列表,WinDbg显示:

kd> bl

0 eu 0001 (0001) (sioctl!DriverEntry)

0暗示断点的id号,e暗示断点的状态为答允,u暗示断点未被理会,即当前加载的模块里未找到切合断点的标记。

输入g返回节制权,在长途机里打开cmd呼吁提示符窗口,输入iocatlapp.exe运行措施,措施当即在DriverEntry处断下(粉红括号):

文件系统驱动编程根基篇之2——标准模型
#p#分页标题#e#

接下来的操纵其实和用户模式下的调试无大的区别,你既可以单步跟踪(F10或F11),在源代码上配置断点(F9),也可以查察变量的赋值和布局(呼吁dv、dt…)等,请读者随意发挥了。如用dt查察某个布局,如:

先用!pcr查察历程或线程内核工具地点,接着查察特定地点的eprocess布局内容:dt -r1 _eprocess 81bef448,尾随_eprocess的这个当前历程的地点可以用!process取得。出格存眷基本篇七提及的iopm:

+0x030 IopmOffset : 0x20ac

+0x032 Iopl : 0 ”

dt -r1 _ethread 8055be40

bl显示的内容改观为:

kd>bl

0 e f8d6a5b0 [d:\0vcprojects\ioctl\sys\sioctl.c @ 123] 0001 (0001) SIoctl!DriverEntry

请读者据资料2与WinDbg辅佐文档当真实践常用的呼吁,同时在网上阅读一些调试好手颁发的文章。只要多实践,可以很轻松的把握这项根基功,究竟我们已经拥有源代码,这和通过反编译来破解信息的难度是不行相提并论的。

五、结语

本篇是驱动编程进修进程中必需跨过的存亡关,假如时间丰裕,发起将资料1的第二至第五章先通读一遍,再精读两至三遍。一些不影响大局的细节(如第三章)粗通即可,无须死记;一些新的观念,如第四章的同步技能,可多耗费时间尽大概尽力的领略这项技能。

驱动编程与汇编语言的进修有相似之处,入门老是先难后易。假如代码在读者的眼中和天书一般艰巨,请不要猜疑本身的本领。不能领略的观念无非是因为在它之前还存在其他未知的常识,把一个复杂的论题解析为若干小块,慢慢办理它们,总有豁然开朗的时候。

本篇不配置参考完成时间,按照小我私家的实际环境,尽快完成入门阶段的进修。

    关键字:

在线提交作业