windows过滤驱动程序设计入门(驱动程序基本结构,设备栈,IRP栈和工作原理)

最近在学习windows驱动设计,认真看了些教材后总结了我认为驱动中都会涉及到,也最重要的概念,和大家分享。如果有说的不对的请大家留言指出。谢谢!

这里主要是写概念,代码涉及的不多也不详细,但是我会说出涉及到的API,详细的使用细节大家可以自己动手搜搜。掌握下面的概念之后,看驱动开发的教材里的代码,或者理解教材里说的内容应该就顺利很多!


 

过滤驱动程序概括:

对于windows驱动程序设计来说,理论上,我们要做的就是创建设备对象(包括完成这个设备对象内部的功能、参数等),然后将这个设备对象绑定到我们要过滤的设备上。一个设备对应一个驱动对象,而一个驱动对象可以生成许多设备对象,这些设备对象是实现功能、完成任务的东西(我们在程序中反复玩弄和折磨的就是他们)。

 

 

驱动的层次结构架构:

 

------------------------------------------------------------------------------------------------------------------------------------------------

上层应用(调用系统API,希望完成一些工作)

------------------------------------------------------------------------------------------------------------------------------------------------

IO控制器(解析上层请求,向下层发IRP包)

------------------------------------------------------------------------------------------------------------------------------------------------

N层过滤驱动(拦截IRP包,做预处理)

------------------------------------------------------------------------------------------------------------------------------------------------

。。。

------------------------------------------------------------------------------------------------------------------------------------------------

目标设备(被过滤设备或者原始设备或者真实设备或者物理设备。。。)(接收IRP包,并按包的指示工作)

------------------------------------------------------------------------------------------------------------------------------------------------

 


重要概念:
1.设备栈:DeviceStack

设备栈是什么?里面装的是什么东西?怎么工作的?

在编写过滤驱动的过程中,我们每生成一个设备对象(代表一个过滤驱动),就一定会把它绑定到我们要过滤的目标设备上。那么如果把多个过滤驱动的对象绑定到同一个设备上是怎么绑呢?系统怎么管理他们呢?答案就是设备栈。原始的被绑定设备和往他上面绑的过滤设备们组合在一起就成了一个设备组。这个设备组会被系统管理成一个栈的结构,形成的就是设备栈。后绑定的设备原本希望绑最下面的目标设备,而实际上绑在了最外面,就像礼品包装纸一样,一层层往外裹。所以当有请求发给目标设备的时候,请求会按栈中的次序从栈顶(最外层)开始依次被栈中的过滤对象依次处理。最后发给目标设备。

 

相关的函数:

当新的设备想要加入设备栈(绑定目标设备)的时候,就会调用绑定函数:IoAttachDeviceToDeviceStackSafe,它第三个参数返回被绑定后的对象指针(其实根据上面的说明能看出来,这个这真就是栈顶)。在这个API的使用当中,大家会发现,一般把第三个参数保存到这个过滤驱动的设备扩展的AttachedToDeviceObject字段,那么通过这个字段是不是可以把IRP依次传递下去?当然,因为它代表当前过滤驱动下一层的设备。

 

绑定设备的三部曲:

第一步:创建设备(准备往其他设备上绑的设备),用IoCreateDevice,第一个参数是设备对象,过滤驱动中填的就是过滤设备。

第二步:为创建的设备设置标志位:把A绑定到B上,就要让AB的标识位一致(这样系统看起来,就以为自己发送IRP到目标设备了),所以创建了A后,要设置一些重要的标识位。

第三步:绑定:调用绑定函数进行绑定,绑上目标设备栈的栈顶设备(这一步结束后,可以通过我们创建的设备对象flag设置设备已经启动)

 

2.服务请求包:IRP和IRP栈

IRP

包里面是什么?怎么产生?怎么工作的?

包里面存放了接收设备要完成请求的工作所需要的一切信息~~~很大很复杂的一个结构体。在WDK的wdm.h中可以找到他。大家在使用的时候会发现,一般都只涉及到一些常用字段。

当用户程序在用户层(Ring3)调用一些系统API,比如(ReadFile)的时候,这些函数的请求最终会被IO控制器接收,然后发出IRP,这个IRP会被向下发送,然后一次又一次的被各种设备处理然后发送给下一个设备。在这个过程中,IRP包又可以被中间的处理设备修改。

 

IRP栈:

那么IRP栈中的内容是什么?系统怎么使用的这个栈进行工作的?

大家看一些教材的时候一定会发现在自己创建的设备过滤到IRP包,然后想对IRP包进行操作的时候,总是会访问IRP栈。上一段中说了,一个IRP的生命中,有可能会敬礼许多段和接收到他的设备的爱情,在这个过程中,IRP中的一些字段难免会不断被改变。而一个IRP栈就像是日记本,记录了IRP的改变过程,所以栈顶的肯定是现在最新的IRP。这就是为什么。。。看下面的函数:

IoGetCurrentIrpStackLocation(irp),每当我们想获得IRP的时候,就这样调用。仔细看这个api中的单词Current,就能猜到这个函数的意思就是访问IRP栈顶、最新状态的IRP(这个最新状态的IRP是经过上层设备各种修改的IRP)。

 

3.下面说下IRP中存的数据

IRP携带数据是通过携带数据所在内存区域的指针来实现的。这样的指针有三个:

UserBuffer,MDLAddress,SystemBuffer。不同的设备会用不同的指针去存要携带的数据。下面是三个指针的原理:

a.SystemBuffer是把用户层空间中的缓冲中的数据复制到内核层空间中使用,这种方式效率很低。

b.UserBuffer是把应用层的缓冲地址直接传递进来,供内核层使用。优点是系统实现的很快,传个地址就行,缺点:内核进程切换,当前的进程被切出去了,访问会结束。为什么会这样?内核空间是共享的,所以内核进程都用公共的空间,内核进程一旦切换,前一个进程遗留的数据肯定就被干掉了~

c.MDL方式是弥补了上面这个缺点,也就是说这个内存描述符表通过添加一个表项,永久的把一段应用层空间和内核空间一段虚拟空间绑定在了一起。这样相当于内核使用访问自己空间的地址,其实是在不知不脚的访问用户空间中的内容。因为这个访问方式是用MDL实现和管理的,所以就算内核当前进程发生了切换啥的,只要MDL表在(这不废话吗?),就永远可以访问到用户空间的那一段内容。而不是简单的把用户空间的一个指针作为值暂时的存到内核空间的一个变量中。

 

 

4.IRP的传递

IRP在驱动设备的工作中起着全程指导的作用,他会在一系列的设备中被转发,自己也会不断改变,那么大家经常遇到这个情况:对于一个过滤驱动来说,他拦截了IRP后,仔细的看了看这个IRP后,发现不是自己感兴趣的,就打算原封不懂得扔给下一层设备处理。在一些教材的示例代码中完成这功能的就一对好基友:

如下:

IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(DeviceObject,Irp);

上面这对基友的工作机制可有讲究了:IoCallDriver单独工作时,效果是自动把irp栈中当前IRP包的下一个包发送到某个真实设备上。。。(因为这个函数认为之前的操作修改了IRP,并且把修改内容压入到IRP栈中新的栈顶地址上,所以让他来调用下一个设备工作,下一个设备收到的IRP也是目前设备处理后的新的IRP,从地址角度来说,就是当前IRP在IRP栈中的地址的下一个地址(新的栈顶)),而IoSkipCurrentIrpStackLocation写在IoCallDriver前面的效果是让IoCallDriver调用的下一层设备收到的IRP包就是本层设备受到的那个。这就完成了所谓的“跳过当前设备”的操作。【抱歉,杂家表达能力有限,是不是说的很晕?】

 

5.IRP请求的完成:

比较简单,调用一个函数:IoCompleteRequest 例程表示调用者的已经完成了对指定I/O请求的所有处理操作,并且向I/O管理器返回指定的IRP报文。

 

6.当然,过滤设备可以绑定也可以解绑Unload:

Unload设备没什么复杂代码,就是调用IoDeleteDeviceIRP。

在这个系列课程中,来自微软的权威技术专家将向您解释Windows操作系统的内部工作原理,从系统架构的大局观出发,逐步展示进程、线程、安全机制、内存管理存储管理等子系统的工作方式。通过对底层原理的揭示,使您更进一步的理解Windows上各类程序的工作方式如何进行错误诊断及性能优化。 本次课程的内容编排得到了国内知名技术作家,《Windows Internals》一书的中文译者,潘爱民先生的大力支持,同时TechNet也邀请到了众多微软一线技术专家进行讲解。这是一个为IT专业人员量身定做的Windows内部知识课程,在介绍原理的同时,也紧密地围绕实际案例常见的故障进行分析点评。这是一个系统的学习Windows底层工作机制的好机会,课程内容深入浅出,精彩纷呈,绝对不容错过。 深入研究Windows内部原理系列之一:Windows的昨天、今天明天 讲师信息:潘爱民 2007年01月25日 14:00-15:30 Level: 300 著名技术作家、微软亚洲研究院研究员潘爱民老师将在这次课程中跟听众分享Windows的发展历程技术精萃,描绘操作系统的体系架构、Vista的内核变更以及今后版本Windows的发展趋势。 深入研究Windows内部原理系列之二:Windows体系结构-从操作系统的角度 讲师信息:张银奎 2007年01月26日 14:00-15:30 Level: 400 操作系统是计算机系统的灵魂管理中心,也是软件系统中最复杂的部分。本讲座将以生动的讲解丰富的演示带您领略Windows操作系统的核心架构主要组件,包括HAL、内核、执行体、系统进程(IDLE、SMSS.EXE、WinLogon.EXE)Windows子系统(CSRSS.EXE、WIN32K.SYS以及子系统DLL)等。并讨论中断管理、对象管理、异常分发等系统机制实现这些机制的基本数据结构。 深入研究Windows内部原理系列之三:Windows体系结构-从应用程序的角度 讲师信息:曾震宇 2007年01月29日 14:00-15:30 Level: 400 从服务器软件到Office办公应用,从联网游戏到即时消息,不管这些应用的复杂程度如何,他们都是一个个在操作系统控制管理之下的可执行程序。本次课程邀请微软全球技术中心专家级工程师,为各位讲解一个程序是如何经历从启动、分配资源、运行、结束这一连串的过程,并且介绍其中的重要概念排错诊断技巧。 深入研究Windows内部原理系列之四:Windows操作系统中的重要基本概念 讲师信息:高宇 2007年01月30日 14:00-15:30 Level: 400 进程、线程、资源分配、内存管理、Win32 API、服务、安全,这些是工作中常常提及但是又无法深入理解的神秘概念。在这次课程中,讲师将介绍Windows中最常见与最重要的一些基本概念. 使大家能够顺利地参与到本系列之后的讨论中去。 深入研究Windows内部原理系列之五:Windows Sysinternals工具集介绍 讲师信息:彭爱华 2007年01月31日 14:00-15:30 Level: 400 Sysinternals Suite(Windows Sysinternals工具集)包含一系列免费的系统工具,其中有大名鼎鼎的Process Explorer、FileMon、RegMon等(Windows Vista下,FileMonRegMon则被Process Monitor所代替),如果把系统管理员比喻成战士的话,那么Sysinternals Suite就是我们手中的良兵利器。熟悉掌握这些工具,并且对Windows的体系有一定的了解,将大幅度的提高日常的诊断排错能力。本课程将以任务驱动的模式,介绍几个经典的应用案例,来介绍Sysinternals Suite的强大功能。 深入研究Windows内部原理系列之六:Vista新特性底层揭秘 讲师信息:彭爱华 2007年02月01日 14:00-15:30 Level: 400 Windows Vista绝非仅仅是具有诸如3D切换、毛玻璃等炫目的界面效果,花钱购买了Windows Vista,而仅仅为了使用其界面效果,难免有点“买椟还珠”的感觉。实际上Windows Vista值得称道的是它具有很多全新的安全特性,例如用户帐户控制、IE保护模式、服务隔离Windows资源保护等等。有了这些全新的安全特性,我们就可以在相当的程度上摆脱恶意软件的滋扰。Windows之父Jim Allchin曾经说过不要满足于只知道How-to、小技巧之类的知识,而是应该深入底层了解其内部原理。只有了解了这些安全特性的内在原理,才能真正了解Windows Vista是怎样精心替我们解决安全问题的,才能真正利用好这些安全特性。本课程将以UAC、IE保护模式为例,介绍这些安全特性的内在原理。 深入研究Windows内部原理系列之七:开机引导过程 讲师信息:张银奎 2007年02月02日 14:00-15:30 Level: 400 Windows的启动是一个复杂的过程,从加载器(NTLDR或WinLoad)开始工作到Windows子系统准备就绪,中间经历了若干个复杂的步骤,包括内核执行体的初始化,创建系统进程线程,对象管理器初始化基本对象,I/O管理器枚举设备并安装驱动程序,启动SMSSWinLogon进程,运行Windows子系统进程。本讲座将解析以上各个步骤的来龙去脉,并探讨驱动的加载顺序、用户登录(Gina,SAM数据库,域身份验证)、系统服务程序、Shell等等启动过程密切相关的问题。 深入研究Windows内部原理系列之八:内存管理揭秘 讲师信息:徐晓卓 2007年02月05日 14:00-15:30 Level: 400 工欲善其事,必先利其器。如果能够深入了解Windows内存管理机制,那么无论在系统配置还是在故障排错方面,都能让我们直达根源,起到事半功倍的效果。本课程将全面介绍Windows内部内存管理机制,包括寻址原理、进程内存空间分布、核心态用户态内存管理原理以及虚拟内存管理原理等。同时将讨论应用程序中内存的使用问题,内存泄露的发生以及排除方法。 深入研究Windows内部原理系列之九:Windows的安全机制实现 讲师信息:张瞰 2007年02月06日 14:00-15:30 Level: 400 Windows如何从操作系统层面保障所有程序的安全?访问控制列表,令牌、系统帐号、SAM数据库、GINA、交互式登陆、COM+,这些概念如何组成一个完整的Windows安全平台?这次课程将解答您这方面的疑问。 深入研究Windows内部原理系列之十:驱动硬件的管理 讲师信息:张伟伟 2007年02月07日 14:00-15:30 Level: 400 驱动程序如何被Windows识别、加载管理?随着Windows的发展,驱动程序的类型作用经历了怎么样的变化?inf文件在驱动安装过程中起到了怎样的作用?Vista的驱动程序有哪些新变化?如果这方面的问题一直困扰着您,那这次课程是绝对不容错过的。 深入研究Windows内部原理系列之十一:存储文件系统 讲师信息:高宇 2007年02月08日 14:00-15:30 Level: 400 课程将在宏观上简要介绍Windows的存储体系, 观察磁盘上的扇区怎样变成用户眼中的文件. 然后深入观察磁盘上的数据结构. 在分析枯燥的16进制数据的同时, 也会大家讨论一些有趣常见的错误现象。 深入研究Windows内部原理系列之十二:网络协议的构成实现 讲师信息:高宇 2007年02月09日 14:00-15:30 Level: 400 课程内容包括Windows中的网络组件, 网络协议,重要网络服务的实现与特点。 Windows中的TCP/IP以及其上的服务将是本节的主要部分。 深入研究Windows内部原理系列之十三:如何诊断调试蓝屏错误 讲师信息:张银奎 2007年02月12日 14:00-15:30 Level: 400 当Windows操作系统检测到来源于系统硬件或内核代码的严重错误时,为了避免继续运行可能导致的更严重后果,Windows会通过蓝屏报告错误并让整个系统以可控的方式停止运行(BSOD)。Windows提供了多种方法来诊断调试蓝屏错误,包括故障转储文件(DUMP)、内核调试以及通过驱动程序注册并接收错误信息。本讲座将解释蓝屏产生的原因过程,引发蓝屏错误典型的根源,并向您介绍使用WinDbg分析DUMP文件的高级技巧。 深入研究Windows内部原理系列之十四:用户模式的程序排错() 讲师信息:喻勇 2007年03月09日 14:00-15:30 Level: 400 “该程序执行了非法操作,即将被关闭”,这是我们耳熟能详的出错报告。程序为什么会崩溃?如何发现崩溃的原因并进行解决?在全面了解了Windows的体系结构程序运行方式后,我们将进一步介绍访问越界、缓冲溢出、内存泄露等故障的原理,并理论联系实际,带领大家使用调试工具来解决一些常见的问题。 深入研究Windows内部原理系列之十五:用户模式的程序排错() 讲师信息:喻勇 2007年03月13日 14:00-15:30 Level: 400 “该程序执行了非法操作,即将被关闭”,这是我们耳熟能详的出错报告。程序为什么会崩溃?如何发现崩溃的原因并进行解决?在全面了解了Windows的体系结构程序运行方式后,我们将进一步介绍访问越界、缓冲溢出、内存泄露等故障的原理,并理论联系实际,带领大家使用调试工具来解决一些常见的问题。 深入研究Windows内部原理系列之十六:使您成为Windows专家的一些学习习惯 讲师信息:喻勇 2007年03月15日 14:00-15:30 Level: 200 在系统的学习了前面的Windows内部原理之后,大家一定对这么多的技术细节深入分析大呼过瘾,也一定想尽快地掌握这些知识。如何学好Windows?如何成为一个技术过硬的IT专业人士?作为这个技术大餐的最后一讲,讲师将跟大家分享一些学习的心得,如何找对突破方向知识重点,循序渐进的进行系统的技术学习。同时也会指出常见的一些学习弊病改进方法。最后,老师将推荐一些重要的书籍学习资料供听众参考。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值