欢迎光临 C++Builder 研究! 本站主要面向软件开发者(Developer/Programmer), 提供 C++Builder, Delphi, C/C++, VC++ 等相关的资料。发布信息请致信给
编程文档
本站首页 www.ccrun.com | 编程文档 |   关键字:

文件系统驱动编程基础篇之1——我们的准备

关键字:文件系统驱动编程基础篇

作者:wskjuf    更新:2008-10-06 21:56:51    浏览:29150

文件系统驱动编程基础篇之一——我们的准备

一、导言

    在四个月漫长的征战后,终于在国庆节的今天完成了基础篇系列。本文写作的初衷很简单,就是给平静的池水中加入一点波澜,如果大家在阅读后感受到一点生气,激起探索未知的热情,笔者也会感到由衷的喜悦。
    本系列文章为业余编程爱好者而写,仅仅作为初学者的一个借鉴,真正的精华存在于参考资料*中。知识的积累将经历从薄到厚,再从厚到薄的反复过程,为了打下牢固的基础,请读者务必在阅读本文的基础上花费必要的时间完成参考资料。

参考资料*:
1.《Programming the Microsoft Windows driver model》第一版(当前阶段主要阅读资料,尝试阅读前两章,体会驱动编程的难度),配套代码位于http://www.oneysoft.com/
2.《Windows NT File System Internals - A Developers Guide》第一章
3.《Kernel Debugging with WinDbg》(随WinDbg软件附带的doc文档,阅读基础部分)
4.《Using Serial Ports》(VMware官方文档)
5.《安装DriverStudio3.2 过程中出现DSDDKEnv8.dll failed to register错误的解决方法
6.《驱动程序和应用程序编译出现的问题及解决方法
7.《Essentials Of Building Windows Drivers》

阅读基础:不限。

本章目的:了解操作系统的基本架构、构建调试器环境、驱动程序编译的一般步骤。


二、基本架构

    为了保证性能,汇编与c成为操作系统编写的首选语言,Windows家族的前辈都不例外,唯独Vista那庞大的身躯,让人不禁疑惑微软究竟如何才能诞下比恐龙还大的怪物。与此相反,WinPE作为维护型操作系统可以被一个32M的U盘所容纳。不管外观上的诸多差异,功能上的强弱区别,我们所关心的是它们的共性——即操作系统的内核。与操作系统密不可分的文件系统,就成为我们研究内核的一条途径。
    Windows采用了基于对象模型(object-based model)的设计方式,各功能划分为不同的组件,两幅常见的架构图如下:


    我们把入口选定为Win32子系统(Win32 Subsystem),它是我们接触最多,也最熟悉的一个子系统。硬件抽象层(HAL)及其以下部分目前不在我们关注的焦点内,我们将精力集中在系统执行层和核心层,它们具体的功能请参看资料2的第一章。
    内核模式下除了屈指可数的几个函数,一切都将是全新的——全新的思想、概念、模型、结构、函数,跨越的幅度不亚于从c语言编程迁移到c++语言,用c语言的思维来学习c++必然会产生阻碍。令人欣慰的是,这里没有特色之流的术语,绝大部分内容都符合人的记忆规律。你将很快掌握设备对象、IRP、IO堆栈等基础结构,同时你还发现以前很难记忆的PEB、TEB、_ETHREAD等一系列无详细文档甚至无文档结构都已有迹可寻,如果你足够勤奋,甚至会在一年左右的时间后就可以阅读天书般的防火墙源码。
    让我们先来完成必要的准备工作吧。

三、调试环境的构建

    在用户模式下编程,除了编译器几乎可以不需要其他辅助工具。想查看输出?直接ShowMessage即可,内核模式下,如果不希望摔得筋折骨断后才有所醒悟,你该在入门前就选好几件宝物——注意它既不是闻西同志的西瓜刀,更不是单车链。

  • Microsoft Visual Studio 200x + Windows IFS Kit and DDK xxx + Compuware DriverStudio 3.x + VAssistX xxx + VMware

    如果记忆力超强的读者,也可以选择C++Builder、Delphi + 插件的形式,有些站点正在致力于推广这方面的技术,对于新手而言,还是用原装货为上策。Windows IFS Kit and DDK是收费软件,电驴上有试用版,依照资料6的说明完成安装,注意选上xp和2000部分;Compuware公司已经改行不做DriverStudio,幸好出家前支持了vs2005,安装完成后,根据资料5打上VisualStudio 2005 Integration fix补丁;VAssistX有试用限制,不巧有人发现不修改代码而使用trial-reset_32清Armadillo壳,可以恢复试用时间,安全而可靠。VassistX增强了编译器的语法提示、代码搜索功能,大大提高了千行规模子程序的阅读与书写效率。VMware虚拟机用于减少重启的烦恼,提高调试的效率。
    经过一阵忙碌后,一个已经设置好的编译器出现了:

  • VMware虚拟机下的Debugging Tools for Windows(即WinDbg)

    读者也可使用VirtualPC虚拟机。在虚拟机上安装双系统(Windows 2000,2003,xp,pe等),可方便删除造成系统启动崩溃的“不良”驱动程序。为了方便,我们把虚拟机上的操作系统称为远程机。首先我们在本地机上安装WinDbg,运行后进行如下设置:

    • 设置符号文件搜索目录,菜单File-Symbol File Path…-填入SRV*c:\symbols*http://msdl.microsoft.com/download/symbols串,它表示使用微软的文件符号服务器。如果你的电脑未联网,则只能通过其他方式获取微软站点上的符号文件,采用本地符号目录,调试时往往会出现一些版本不匹配的问题。符号文件非常重要,如果WinDbg找不到合适的符号文件,将无法解析代码里的数据结构。文件符号服务器上的符号文件用于解析操作系统文件(dll, exe等),而你的源代码将编译产生驱动程序的符号文件。
    • 菜单File-Open Executable…-随意选择一个可执行文件进行本地调试,WinDbg将搜索是否已经存在必须的符号文件,如果无,则通过互联网连接文件符号服务器下载必要的符号文件,保存的目录是c:\symbols。之所以进行这一步,是帮助初学者在连接远程机出现长时间的延时时,确定不是因为下载的原因造成的。
    • 运行虚拟机,打开远程机系统根目录下的boot.ini文件(可能是隐藏文件),为操作系统复制一新行,并在后添加/debug /debugport=com1 /baudrate=115200,指明连接的方式(串口连接)和速率(115200比特率)。如图是安装了两操作系统的boot.ini文件:

    重新运行远程机,启动界面如:

    • 为虚拟机添加虚拟串口:关闭虚拟机,点击配置选项Eidt virtual machine settings,选择命名管道方式配置虚拟串口com1:

?

    • 测试虚拟串口:运行远程机,选择debug模式进入,此时将比正常启动多出近30秒的黑屏时间,如果你的硬盘马力强劲,你会听到运转的沙沙声^_^,接下来的情况将和正常启动时相同。在本地机上运行WinDbg,点击菜单File-Kenerl Debug…,首次连接时按左下图进行配置,确定后WinDbg将开始尝试远程连接。为了加快连接速度,不妨多按几次重新同步的快捷键Ctrl-Alt-R,如果上述设置无误,则虚拟串口标志将不停闪动(中下图最右),连接成功后,WinDbg出现类似信息(右图):

??

    • 调试器连接了远程机后,就获得了远程机的控制权,远程机则处于停机状态,此时可以查看内核的情况,如果希望它继续运行,只需要在调试器的命令行窗口输入g命令,则调试器归还控制权,远程机将继续运行。

 

  • http://www.osronline.com/index.cfm下载您中意的工具。
  • 特别值得一提的几个小工具是:Dbgview,Driver Installer、IrpTracker、DriverMonitor和EzDriverInstaller,后两个工具为Driver Studio附带。
  • 练习WinDbg的使用,尝试用(二)- 二)的方式单步跟踪一个简单的可执行程序,学习如何设置断点。

    最后一步是个难点,请根据资料3努力的完成这个工作。

四、驱动程序的编译

  • sources、makefiles和dirs文件

    使用DriverStudio的一个目的是,借用vs强大的IDE编写代码,而调用DDK的编译器进行编译。早期的vs编译器也支持驱动代码的编译,但随着DDK的发展,现在它已经完全脱离了vs,两者不再保证编译代码的一致性。为了保证正确性,我们需要使用DDK的编译器来完成编译的工作。
// 本文转自 C++Builder研究 - http://www.ccrun.com/article.asp?i=1054&d=56457m
    基于效率的原因,我们还需要学习使用sources文件,它支持众多的编译指令,可以实现复杂的编译配置。驱动编程中,makfiles文件是一个无关大局的配角,一般无须改动,尽管它是必须的。如果源文件非常复杂,分布于多个目录,包含了多个工程,则可编写dirs文件。编译器通过dirs文件,找到各目录下的sources文件,逐一完成编译。下面我们将介绍sources文件的基本写法,更多指令的详细用法可查阅资料6或Msdn。
    sources是一个无后缀名的文本文件,示例如下:

TARGETNAME=pnpevent
TARGETPATH=obj
TARGETTYPE=DRIVER
USE_PDB=1
INCLUDES=..\..\..\generic
#TARGETLIBS=..\..\..\generic\obj$(BUILD_ALT_DIR)\$(CPU)\generic.lib \
TARGETLIBS=..\..\..\generic\obj$(BUILD_ALT_DIR)\i386\generic.lib \

SOURCES= DriverEntry.cpp \
stddcls.cpp \
control.cpp \
readwrite.cpp \
driver.rc

    #号表示注释,而*号表示目标平台类型,编译时会被Build工具替换成相应的串,如替换成“I386”。
    TARGETNAME指明驱动程序名,TARGETPATH指明生成的路径(如果没有其他指令,编译器生成的是以obj打头的路径,如objchk_wxp_x86\i386)。TARGETTYPE指明代码类型,可创建普通驱动sys、内核模式的dll、库文件lib、用户模式程序exe、用户模式的dll。TARGETLIBS指明需要引用的外部lib库文件。
    INCLUDES指明需要引用的头文件目录,SOURCES指明本次需要编译的文件,文件名后的\表示下行仍为源文件。
还可以使用C_DEFINES和USER_C_FLAGS来定义宏。对于若干年前的驱动代码,编译器可能会提示无法识别某些废弃的编译指令,视情况手工删除或更改成等价指令即可。

  • 编译DriverStudio的VdwLibs2005.sln工程

    该工程位于Compuware\DriverStudio\DriverWorks\source目录下,vs2005编译器加强了语法的规范性,不修改源文件是无法完成编译的。为此,请参考资料6,按照图三、(一)的方法直接调用DDK进行编译。
阅读资料1第三章的错误处理小节,编译附带的源代码Chap3\SEHTEST,学会使用DriverMonitor来加载驱动、Dbgview来查看该代码的输出信息。

五、代码书写规范与编译警告的处理

    书写规范可参考本站的《华为编程规范和范例》,强调一点,驱动编程中使用了众多的宏,为避免宏扩展带来的潜在问题,使用if,while,for等时,其下的子句都须以{}扩之。缩进不规范的代码可通过Alt+F8修正。

if (x)
    return y; // 不推荐
if (x)
{ // 标准格式
    return y;
} // 标准格式

调高编译器的告警级别,使任何警告都被当作错误而停止编译,这种严谨的态度有助于减少潜在的错误。建议在sources文件里至少设定W3级别:

MSC_WARNING_LEVEL=-W3

六、学习的误区

    缺乏必要的计算机科学技术的理论基础,是非专业的编程爱好者遇到的一个最大的问题。在这个问题的处理上,如果采取回避的态度,相信很快就将潜力用尽,再也没有上升的空间。有的人编了几年程序,却还在害怕阅读其他语言书写的代码,是这个问题的一个表现。如果看到了这个问题,并希望解决它,也需要采取正确的方法。贪多求全,希望先把基础理论一口吞下再来实践编程的思想也是错误的,因为理论仅仅是实践的一个抽象,两者必然存在差别,大脑也需要在实践中建立起可靠的影像,而不是“大概,也许,基本上”这样的一种客套话,这也是能力的体现。
    我们的建议是,根据自身的实际情况,在每一个发展阶段采取先学习理论再实践,或先实践再学习相应理论的方式,螺旋般的向上,速度虽然稍慢,却能为自己积累下发展的潜力。一个实际的例子是,计算机系的学生在入校后的前两年,计算机的实践水平往往比不上别的院系的学生,一旦他们发现实践上的很多问题可以通过已掌握的基础理论来解释之后,两者的前进速度就有了质的差别。高手的一个特点是哪怕只给他透露了一个关键的单词,你所保留的秘密很可能就被完全破解了,而对于菜鸟而言,即使把金山搬到门口,也还是身在福中不知福。
    在基础篇中,我们推荐了大量的示例代码,这些代码可以帮助读者更好的理解基础的理论。
    完成了基础篇,您仍然处于文件系统驱动编程的边缘,对它的理解甚至比不上采用了速成大法学习的其他人,您的收获则是奇怪为什么自己先前写了如此多的垃圾代码?您将大大扩宽自己的眼界,看到控件之外的许多更有意义的知识。
    唯一没办法帮助大家的事情,就是外文阅读水平了。我们只能鼓励还仅仅掌握着1.5国语言的朋友,人手一册金山词霸,首页google在线翻译,每日半篇RFC,不出两月,拿下Msdn。当然如果你能在Msn上结交到海外的留学生,他们对您的帮助将会更大。
    编程能力以2万行作为分界点,还达不到这个要求的朋友,请努力吧。
    华老师有句名言,“天才在于勤奋,聪明在于积累”,技巧性的东西固然可以帮助您提高效率,但始终无法代替基础,如果您想在科技领域真正有所成就,就请遵循这句话。

七、结语

    基础篇将仅仅讲述一些与WDM(Windows Driver Model,KMDF相当于WDM的封装类,Vista已自带)驱动编程有所关联的基础知识,限于能力,并不追求系统性和完整性。资料1作为大师级的著作,是笔者推荐的主要学习资料,本文中大部分驱动示例来源于它的配套代码。
    留给初学者的一个问题是,究竟VMware的虚拟串口支持多高的通信速率呢?
    本文作为下场之前的热身,参考完成时间为一至两个星期。

上篇文章:现有 Delphi 项目迁移到 Tiburon 中的注意事项
下篇文章:浅析C++中内存分配的方式
相关搜索:
  中搜索“文件系统驱动编程基础篇之1——我们的准备 ”相关内容
  中搜索“文件系统驱动编程基础篇之1——我们的准备 ”相关内容
  中搜索“文件系统驱动编程基础篇之1——我们的准备 ”相关内容
  中搜索“文件系统驱动编程基础篇之1——我们的准备 ”相关内容
  中搜索“文件系统驱动编程基础篇之1——我们的准备 ”相关内容
  中搜索“文件系统驱动编程基础篇之1——我们的准备 ”相关内容
C++Builder 研究 - http://www.ccrun.com © 2001,2011  总访问量: 44026037  来访IP: 54.81.79.128  晋ICP备05000574号
Tags: Borland CodeGear Embarcadero C++Builder Delphi VC++ C/C++ RAD Studio BCB BDS Source Code VCL MFC COM SDK Components Controls Developer Programmer 编程学习资料 源代码 源程序 源码 编程文档 经验技巧 组件 控件 元件 开源 函数 软件开发 一切尽在C++Builder研究!