intel ME是什么驱动

1两种硬盘加速技术解析

  【PConline评测】11月中旬,Intel发布了全新的品牌旗舰X79平台,以取代老旧的X58平台。X79平台从性能和内存性能来说都是很强大的,但是其磁盘规格和性能就比较让人失望,而且居然还不支持Z68都有的智能响应(SRT)磁盘加速,实在让人大跌眼镜。

  在此背景下,华硕在自己的X79主板上提供了智能响应的替代品“华硕固态硬盘缓存加速技术( SSD Caching)”,感觉让人充满期待,为了对比这项技术和智能响应,我们进行了今天的测试,结果让人惊讶,5000元的Z68平台居然能完胜万元级的X79平台!到底这是怎么回事?请看下文分解!


5K平台赢万元旗舰?Z68+X79实战热门游戏

华硕固态硬盘缓存加速技术介绍:


华硕固态硬盘缓存加速技术

  华硕固态硬盘缓存加速技术( SSD Caching)是华硕在X79上推出的、作为Intel智能响应替代品的混合存储技术,能够通过机械硬盘+固态硬盘组合成混合存储,可以使用各种容量的固态硬盘,兼顾了机械硬盘的大容量和固态硬盘的高速度,而且一键启用,无需重装或者重启,异常方便。

  华硕固态硬盘缓存加速技术能按用户的使用自动缓存经常使用的数据,明显提升磁盘的读取速度,加速系统启动速度,据官方称最大提升可达3倍。

  和智能响应繁琐的设置不同,华硕固态硬盘缓存加速技术非常易用,无需进入繁杂的BIOS或Option ROM,只需装上软件即可一键启用。

  华硕固态硬盘缓存加速技术没有“增强”、“最大化”之类莫名其妙的术语,与一般的智能响应相比,它不仅不依赖于主板芯片,而且搭建起来非常容易,操作界面也很简单,更重要的是对固态硬盘的容量没有上限和下限闲置,自由度更高,并且具备防止数据丢失的功能。

Intel智能响应技术介绍:

  智能响应技术(Smart Response)主要是利用SSD固态硬盘作为机械硬盘的高速缓存来实时缓存常用的应用程序,从而提升系统的整体性能(尤其是读取性能)和响应速度,据Intel官方宣称这项技术带来的性能提升可以高达4倍。

  Intel智能响应技术(Smart Response)可以划分18.6GB~64GB的SSD固态硬盘容量作为高速缓存,如果用户的SSD固态硬盘容量超过了64GB,那么剩下的容量仍然可以正常使用。

  一般的智能响应技术安装设置还是比较麻烦的,用户可能需要在主板BIOS界面、Option Rom RAID配置界面等地方好好设置一番才能启用,而且还可能需要重装系统和备份数据,卸载起来也比较繁琐,总体不是很方便。

  智能响应技术推广的一个门槛就在于较为复杂的设置和需要重新安装系统的麻烦,为了使用户能够更轻松地用上智能响应,技嘉推出了易倍速(Ez Smart Response)软件,这个软件能自动完成相关软件的安装、设置,用户无需重装系统、无需相关知识都可以启用智能响应技术,非常方便和人性化。

  本次测试主要关注华硕固态硬盘缓存加速技术的理论和应用性能表现,我们选择了i7 3960X处理器,4通道大容量内存,搭配GTX 570独显,以确保平台具备足够强大的处理器性能和图形性能,不会在游戏测试中形成这方面的瓶颈。为了方便对比华硕固态硬盘缓存加速与Intel智能响应在应用和性能方面的差别,我们还采用了一个i7 2600K平台作对比平台,不过由于两款i7处理器的性能有一定的差别,因此测试数据没有绝对的可比性,仅供参考分析。

  测试方法方面,我们用Crystal Disk Mark等软件测试理论性能,再用使命召唤8等游戏测试应用性能,由于华硕固态硬盘缓存加速技术主要是一种针对应用的技术,因此我们的测试会更偏向于游戏应用测试。

  本次测试使用的主板时华硕 P9X79 Deluxe,这是一款基于 X79芯片的大板,支持全新的LGA 2011接口的SNB-E系列高端i7,采用第3代双智能处理器,配备多达20相供电和2+2相内存供电,可以安装附带扩展实现BT GO 3.0功能,支持x16+x16双卡或x16+x8+x8三卡多种多卡互联,并且具备华硕特色的华硕固态硬盘缓存加速技术、图形化中文BIOS和一键BIOS升级等各种特色功能。


华硕固态硬盘缓存加速技术

  就目前来说, X79貌似还不能支持那样的智能响应技术,不知道Intel日后会不会加上,反正华硕已经提出了他们的解决方案,华硕在X79平台上推出了华硕固态硬盘缓存加速技术( Caching),只需把机械硬盘和固态硬盘接到第三方SATA磁盘接口,并安装使用华硕的AI Suit II即可实现机械硬盘+固态硬盘缓存加速,大幅提升硬盘的读取性能。

  技嘉 GA-Z68X-UD7-B3主板基于 Z68芯片组,采用ATX大板设计,延续了技嘉一贯的豪华用料风范。主板支持最新LGA 1155接口的第二代/i5/i7处理器,支持K系列不锁倍频的处理器。 特色技术方面,技嘉 GA-Z68X-UD7-B3集合了超耐久3、333、真24相供电设计、Driver MOSFET、Turbo USB3.0、云超频等技术,彰显其高端定位。

智能响应技术,可让固态硬盘成为“硬盘(HDD)的缓存”,以提升硬盘的存取速度,实现速度与容量间的完美平衡。

3华硕固态硬盘缓存加速组建指南

固态缓存加速组建指南:


基本硬件:,机械硬盘,固态硬盘

  要组建华硕固态硬盘缓存加速平台,、内存等硬件就不用多说了,最关键的是有支持华硕固态硬盘缓存加速的华硕主板,一个机械硬盘和一个固态硬盘。目前,用户只能选择用一个固态硬盘去给一个机械硬盘加速,其他多出来的机械硬盘是不会享受到缓存加速的好处的。


把硬盘连接到第三方SATA口

  华硕固态硬盘缓存加速技术是依赖于Marvell 9128 SATA控制芯片的技术,与主板的芯片无关,因此用户必须把需要加速的机械硬盘和固态硬盘连接到第三方SATA接口。

  华硕固态硬盘缓存加速软件整合在华硕 AI Suite II软件中,用户可在安装AI Suite II时进行选择。

  打开华硕固态硬盘缓存加速不需要手动调整SATA控制器工作模式或重启、重装系统,但是需要清空固态硬盘。

  确认继续后,软件就会开始对固态硬盘进行初始化设定,在我们的100G 固态硬盘上来说,整个过程需要消耗10分钟左右的时间。

  初始化完成后,华硕固态硬盘缓存加速就已经成功打开了。与智能响应技术相比,这样的组建、设置方面明显要更加简单、更容易操作。

4典型智能响应组建指南

典型智能响应组建指南:

  智能响应是 的独有功能,要启用智能响应技术,我们必须先把连接到Z68原生SATA口上,并把SATA控制器(Z68)设置到RAID模式,一般来说这是需要重装系统的,否则会蓝屏无法开机。

  在开始组建智能响应平台之前,请注意备份你的重要数据,虽然智能响应RAID丢失数据的可能性比一般的RAID模式要低,但是有个后备方案作保险始终是好的。

  默认情况下,开启RAID模式后,的BIOS一般都会打开Intel 的ME子系统,如果没有,请手动到BIOS里找到相关选项,打开ME子系统。


ME子系统与南北桥并列

  一些主板的ME子系统设置到了芯片组页面,和南北桥并列。提醒一下,即便用户打开了ME子系统,只要SATA控制器不是设置到RAID模式,ME就不会自动加载

  要启用智能响应技术,我们必须打开SATA控制器的RAID模式。


SATA控制器设置选项

  这个选项一般都在专门的SATA控制器设置选项里,对于这款主板就是在高级配置页面的SATA配置选项里。

  设置完SATA控制器模式之后,我们一般就可以去安装系统了,如果有什么不对劲,请在开机看到ME子系统提示时按Ctrl+I,进入ME子系统管理页面,关闭所有RAID设置(Reset Disk to Non-RAID)。注意,这个ME管理界面主要是用来排错/卸载时使用的,一般情况下我们只需使用桌面的ME管理软件即可。

  如果系统在安装时SATA设置模式是IDE模式,那么一般将SATA模式调整成RAID模式时就会无法启动,出现蓝屏、重启等现象,因此我们需要重新安装一次系统,过程并不复杂,相信无需多说。

6、安装各种驱动,安装Intel快速储存软件和管理引擎(ME)

  重装完毕之后,我们就可以启动到桌面,并安装相关驱动和软件,要实现智能响应技术,我们必须要有快速储存软件和管理引擎软件。

  如果用户的安装时正确的,那么用户应该就能看到一个“加速”选项,在里面,我们可以选择启用智能响应加速功能,把设置用来加速机械硬盘。

  打开加速功能可能会花点时间,因此用户需要耐心等待一下,打开成功后,我们应该就能在加速页面看到加速相关信息。

  如果用户觉得有必要,还可以把加速模式从默认的“增强模式”调整为“最大化模式”。最大化模式下磁盘写入会先经过SSD作缓存,再到机械硬盘,因此写入性能会比增强模式更好,但是也需要冒更大的数据丢失风险。

5技嘉易倍速加速搭建指南

  典型智能响应的设置启用方式非常繁杂,对于操作水平不高的用户来说简直是灾难。为此技嘉通过软件包装智能响应,推出了更加简单的“易倍速”,说白了就是自动设置、启用智能响应技术,让小白也能轻易成倍地提高磁盘速度。

  我们从技嘉官方下载了最新版的EZ Smart Response软件来进行测试,下载回来的文件是一个7-Zip制作的自解压包,用户需要先把安装文件解压出来并运行Setup.exe才能安装。

  安装界面很简单,点“安装”(Install),一路“下一步”(Next)就可以了。

  安装完毕后,运行软件会弹出对话框,提示用户电脑会重启,点“确定”的话就会重启并开始自动完成智能响应相关设置,电脑需要经过两次重启才会进入到下一步。提示一句,这期间最好不要把HDD模式的插到电脑上,否则可能会出问题

  重启之后电脑不会进入桌面,而是进入上图一样的界面,软件提示即将清空SSD内数据,点OK就会清空SSD数据并重启。

  重启之后,电脑就应该已经自动安装智能响应软件并默认启用增强模式,到此智能响应就已经可用了,我们可以打开Intel快速储存软件看到相关的信息。

  Intel快速储存软件界面非常非常大,因此我们截取其中一部分来让用户看得更加清楚。增强模式主要增强机械的读取性能,不过对于写入性能方面则没有多大帮助。

  选择“加速”页面,用户就可以选择切换到“最大化模式”。最大化模式下可以同时增强磁盘的读写性能,但是传输中的数据可能会因停电而丢失。

  CrystalDiskMark软件是一个测试你的或者存储设备的小巧工具,简单易于操作的界面让你随时可以测试你的存储设备,测试存储设备大小和测试数字都可以选择,还可测试可读和可写的速度。


最佳成绩:Intel 智能响应

  ATTO Disk Benchmark是一款简单易用的磁盘传输速率检测软件,可以用来检测硬盘、、存储卡及其它可移动磁盘的读取及写入速率。该软件使用了不同大小的数据测试包,数据包按0.5K、1.0K、 2.0K直到到8192.0KB进行分别读写测试,测试完成后数据用柱状图的形式表达出来,很好的说明了文件大小比例不同对磁盘速度的影响。


最佳成绩:Intel智能响应

  理论测试小结:理论性能测试中,Intel的智能响应大获全胜,读取成绩明显比华硕的固态硬盘缓存加速高,这可能是因为Intel智能响应更加敏感,也可能是因为华硕的方案用的是桥接的第三方芯片。

7游戏测试:使命召唤8、战地3

1、《8:现代战争3》测试

  《使命召唤8》继承了“现代战争”系列优秀的画面,为我们展现世界顶级特种部队依托高科技武器在小规模局部战争中的风采,游戏的画面呈现和枪械手感也再次达到了一个新的高度。《使命召唤8》的游戏背景又回到了“现代”,故事紧接着《使命召唤6:现代战争2》以及《使命召唤4:现代战争》,大家熟悉的Price大叔和Soap小强再次回归。这些游戏中的重要角色早已凭借着电影般的剧情,被大家所牢记。测试场景为Hunter Killer,分辨率,高画质。

  《战地3》采用的全新DX11“寒霜2”引擎,在3D建模精度、画面渲染、特效呈现、物理效果等方面,都达到了当前PC游戏的顶点水平,为次世代DX11游戏大作树立了一个标杆。我们测试所用关卡是Comrade,分辨率为,高画质。

  测试小结:从两款热门游戏的测试成绩来看,华硕的固态硬盘缓存加速和Intel的智能响应都是很有效果的,其中使命召唤8从磁盘加速技术中受益尤其明显,载入时间降到1/5的水平。

8游戏测试:孤岛危机2、正当防卫2

3、《孤岛危机2》测试

  《孤岛危机2》是第一代孤岛危机的正统续作,游戏采用与一代不同的全新引擎CryENGINE 3所制作,并且第二代将打破一代的PC独占,还将登陆主机平台。那自然就好考虑如何实现PC版画面不仅不缩水,而且要比前作更好,而且还要兼顾主机平台的可实施性,这就要拜CryENGINE 3的强大功能所赐了,Crytek承诺他们能做到这点。测试场景为“Out of Ashes”,分辨率为,高画质,打开DX11特效。

4、《正当防卫2 》测试

  《正当防卫2》依然采用了Rico Rodriquez作为本作的男主角,事情发生在前作发生的几年之后,Rico被要求在东南亚的一个小岛Panau上找到Tom Sheldon,并将其杀死。而具体的做法就是不停地破坏,制造混乱,然后团结某些力量获取情报,最后找到Tom,最终将其杀死。测试采用游戏自带Benchmark,场景为黑暗之塔,分辨率为,特效全开。

  测试小结:在孤岛危机2和正当防卫2两款游戏的测试中,磁盘加速表现出来的效果并不如使命召唤8和战地3明显,但是最少也有7秒提升,长期算下来还是相当省时间的。

华硕固态硬盘缓存加速 VS 不加速 测试成绩总结

有钱人才买X79,再加大10%投入,游戏等待时间减少:

  华硕固态硬盘缓存加速目前只在X79平台上有,有此功能的华硕X79最便宜也要卖3299,比同级产品至少贵300元,再加上M4固态硬盘,享受固态硬盘缓存加速需要多加1000元有多的投入。不过这样的数目在X79平台总价面前并不算什么,算它多加10%投入又如何,游戏等待时间平均减少55%,吸引力还是挺强的,值

华硕固态硬盘缓存加速 VS Intel智能响应 测试成绩总结

  从上面的加速和不加速对比可以看出,华硕固态硬盘缓存加速效果的确是很不错的,而且其安装设置耗时、安装卸载难度都明显比Intel智能响应更理想,遗憾的是目前这项技术只在昂贵的X79上有,花Z68平台两倍的价格买X79玩加速,等待时间只相对Z68减少10%而已,实在不是很划算。从另一个角度考虑,开启智能响应加速的Z68平台比无加速的X79更快载入游戏,按上面的价格算就是4600元 vs 11000元,所以游戏玩家还是买Z68玩加速比较靠谱。

  总的来说,华硕固态硬盘缓存加速技术在安装耗时、安装难度和实际使用效果方面都是很令人满意的,而且目前它是X79上唯一的能够替代Intel智能响应的技术,其独创意义是很大的,这是项很好的技术。而目前这项技术最大的问题就是推广,如果只在X79上有,那当然是难成气候的了,我们期待华硕为我们带来支持固态硬盘缓存加速的AMD主板或者7系列主板!让更多用户体验这项技术的好处!

您应该仅使用HP站点上可用的笔记本电脑上的图形驱动程序,因为他们可能已经修改/自定义了其硬件平台的驱动程序。

from .... 在这里非常感谢辛苦的译者,用他的话说就是:“可以说,驱动相当不好上手……”。呵呵,为了跟大家共同分享,我将会保持此文和他的更新。

第一章 开始一个驱动项目

在这章里,我会概述一下驱动的编写流程。当20世纪80年代IBM将MS—DOS作为他们个人电脑的操作系统时,我包括 个人计算就是从那时开始的。当时IBM和Mircosoft的决定现在仍然能够体会到,因此一些过去的看法会帮助的理解驱动的编写。

Windows driver model(WDM)驱动程序运行在两个完全不同的操作系统环境中。并且我将在这章概述一下这些环境的体系结构。Windows XP,像windows2000和更早期的windows版本一样,提供了一个正式的框架结构使驱动在执行代表应用程序和其他驱动的I/O操作时能执行一 个被明确定义的任务。Windows

这有几个写单独功能WDM驱动的例子:

几种串行接口的的读卡器

ISA卡支持独立识别读写传感器

原来,WDM过去可意兼容所有版本的Windows操作系统。因为发行计划和更多的考虑,自从Windows 98以后发行的版本中已经包括了支持月来越多的很有用的核心功能,有些时候甚至是基本的,为了增强和方便程序设计。有一个例子是IoXxxWork- Item家族的功能,在第14章中介绍,它被加入了Windows 2000中用来取代缺乏稳定性的ExXxxWorkItem 系列。如果你不作其他的,一个叫做IoXxxWorkItem的例子不能在Windows 98/Me中使用,因为操作系统不能导入它的功能。MmGetSystemRoutineAddress是另一个不能在Windows 98/Me中使用的功能,不幸的是,你甚至不能在运行时调用相关的功能项。如果它的实现不理想,WHQL测试使所有的驱动标记访问 ExXxxWorkItem

在Windows 98/Me中,一种名为NTKERN的VxD实现了WDM的某些核心的支持功能。在附录中会有更详细的讨论,NTKERN依赖一个定义了的输入符号来实现 随时的载入。你可以定义你自己的输入符号,这就是WDMSTUB怎样来管理我建议你自己的二项兼容的驱动中使用的未定义的符号。

这个伴随的目录中包括WDMCHECK的效用,你可以运行在Windows 98/Me系统中来检查一个驱动丢失的输入信号。如果你已经开发出了一个在Windows XP中运行的相当好的驱动,我建议你先将它拷贝到Windows 98/Me系统中在WDMCHECK中运行。如果WDMCHECK显示你的驱动调用一些不支持的功能,然后再检查WDMSTUB是否支持这些功能。如果 是,只要将WDMSTUB加入到你的驱动包里,将会在附录中介绍。如果不行,修改你的驱动或是发E-Mail问我如何修改WDMSTUB。通过这些你可以 最终结束一个二元兼容的驱动。

一个串行接口驱动。Windows 98/Me的驱动VxD在上升沿提供了VCOMM端口驱动接口,而Windows 2000/XP驱动是一个WDM驱动,在上升沿提供了一个充足和严格定义的IOCTL接口。这两种上升沿定义是明显不同的。

一个为非标准的USB大容量存储器提供的驱动。为了Windows 98/Me,你要写一个VxD适合输入输出分层管理的多层驱动。为了Windows 2000/XP,你要写一个单独功能的WDM驱动在上升沿接受SCSI的请求块在下降沿和USB设备来进行传递。

为这两类设备,在WDM之前微软定义了一个可适应的驱动架构:

小型机系统接口(SCSI)适配器使用一个“SCSI 迷你接口”驱动,它不使用任何标准的核心支持功能而是依赖于从SCSI.SYS或是SCSIPORT.VXD输出的特殊的API代替,这种迷你接口可以使 用于系统之间。

网络接口卡使用一中“NDIS迷你接口驱动”它是依赖于从NDIS.SYS和NDIS.VXD输出的特别定义的一种 API,来实现相应的功能。过去,NDIS迷你接口驱动可以在系统之间使用,但是现在几乎不使用了。网络协议驱动和被叫做“媒介”的驱动提供了过滤的功能 和网络驱动接口标准。

1.4 概要管理和检查列表

    如果你是一个(程序)开发管理者,除非你不必为“将硬件设备投入市场”负责,否则有一些有关设备驱动程序的情况你需要了解。首先,你需要决定:是否你需要 一个(贴近)用户的驱动程序,还要决定其类型。(文章)之前的部分应该已经帮你做了这样的决定,但是你可能还需要雇佣一个专业的咨询顾问(以便)在这方面 给你最直接的忠告和建议。
    如果你经过评估之后,自信需要一个用户化的驱动程序,之后,你就需要找到合适的程序员。严酷的事实是:WDM驱动程序设计确实有些难,并且只有资深的程序 员有能力把它做好。很多公司都需要这种程序员,但是大多数(公司)都雇佣不起。如果你是这种情况的话,你就有两个基本选择:培训那些已经在你的团队的人 员,雇用一个程序员--他已经具备了必要的能力--作为咨询顾问或者合同程序员,或者从一个专业的驱动程序设计公司寻求支持。你需要根据自身的个性需要来 衡量这些选择,(以便)从中进行挑选。
    一旦,合理确切的说明了硬件将如何运转,驱动程序设计就应该开始了。你应该做好这样的心理准备:在驱动程序开发过程中(会)暴露一些讨厌的(新)发现, (此时)说明(文档)(也应该做相应的)修改;你还应该料想到你的硬件、硬件/软件接口和驱动程序的蓝图将被多次的重复(修改)。
    而且,驱动程序设计将比你最初预想的经历更长的时间并且消耗更多的投入。所有的软件都遭受时间和金钱的(双重)开销。驱动程序设计的这种附加消耗主要是以 下原因(造成):硬件和软件人员之间的沟通困难,在说明(文档)和DDK文件(内容中的)歧义,所有部件中(可能出现的)程序错误,以及设计和生产中的延 迟。
    在大多数情况下,你将使你的硬件和软件服从于“视窗硬件品质保障(WHQL)”以便获得顺利安装的数字签名和获准成为微软logo目录中的一员。你将自己 进行大量的测试,并且你将需要具体的计算机安装(程序)以便完成(测试),因此,为你的硬件部件找出最初的测试需求不可避免的成为了你工程的最后部 分。(举个例子:测试一个USB设备,要求你具备一个具体拓扑结构(计算机)中的各种声音硬件,即使你的这个硬件和声音或者其他的常用媒体没有任何关 系。)
    还要准备你的商业后续工作:同WHQL合作。至少,这将要求你从Dun和Bradstreet(或者从同等的商业团体取得许可)获得一个“数据广义编码系 统”的号码,并从Verisign(获得)一个数字签名证书。类似这种著作,DUNS编码是免费的,但是Versign认真却不是。运作通过联合公司的所 有工序将需要时间。
    尽早留意最终用户将如何安装驱动程序软件。大多数外设零售商宁愿提供一张包含通用安装程序的CD-ROM,因为编写安装(程序)是一个漫长的工程---- 需要花费一个资深程序员几个星期的时间。驱动存储网站(现在)非常普遍,并且对安装问题给予了特别关注。
    驱动程序可以用两种方式提供统计和管理信息。视窗“设备管理器(WMI)”系统为各种类别的二进制数据提供一种独立的语言(通道)。微软公司已经为特定种 类的硬件建立了标准的WMI类型,你自己的工业群组可能也已经建立了其他的标准----你的驱动程序应该遵守的标准。第十章包含的信息就是如何遵守微软的 标准,但是查明如何适应其他的工业(标准)可能是你公司商业代表的工作。
    提供管理信息的第二种方式:系统事件纪录的意义,这种纪录是视窗NT一开始(就有的)部分,它为系统管理员提供一个捷径:了解最近哪些优先级提高了。你的 驱动程序应该报告的是:那些能够引起系统管理员注意的以及具备可操作性的事件。无论如何,你的驱动程序都应该与资深的系统管理员协商,以便决定记录那些事 件,这样将避免乱七八糟的(信息)无一例外的记录到日常纪录。你的驱动程序的可执行文件也很可能包含了消息文档----一种特殊的通晓各种语言的消息,并 且让一个博学的作者创作这个文档是个不错的主意。(我并不是说你的驱动程序不能做这样的事,但是他或者她可能并不是最好的选择。)
    另外,对于一个驱动程序,你可能需要控制面板和其他的配置软件。驱动程序设计人员和一位专家--在互相干扰用户(方面)--应该合作构建这些组成部 分。(这些组件)从它们随着安装驱动程序(一起)被安装开始,它们将成为WHQL数字标志包的一部分,因此它们也将随着驱动程序的结束而同时结束。
    最后,不必调整驱动程序的无关紧要的细节。一个好的驱动至少具备一个顺利的安装(界面)作为产品的外部表现。简而言之,如果你的驱动使得操作系统崩溃, (驱动)检查者将提醒公众,并且任何没有读到检查(报告)的人都将愤怒的把你的产品推给商店。由于你的驱动,在那些系统被摧毁的人们当中,你甚至没有任何 一个回头客。所以对于一个资金不够雄厚的驱动开发者,一个短视的决定,就很容易导致一个你的底线上的戏剧性失败结果的很快来临。这个建议对于发展中国家的 硬件制造商尤其重要,(因为)这些(厂家)的管理者趋向于寻找任何可能去降低成本。我建议:应当将驱动开发作为一个基础投资决定。


概括来说,用心的依照以下步骤来计划你的开发方案:
1.评估驱动需要和选择编程人才。
2.编辑 硬件说明文档----完全满足驱动工作开始的需要。
3.供驱动测试的硬件雏形。
4.作为原始构思:驱动程序和硬件/软件硬件接口。
5. 在所有操作系统中测试安装文件。
6.提前配置控制面板和其他所需软件。
7.测试和完成WMI和事件纪录功能。
8.WHQL自检通 过并且满足需要。
9.通俗安装程序完成。(不属于WHQL的需要部分)
10.准备刻录光盘以及随产品附送。

注:加括号的是作者添加的文字,主要是连接上下文以及代词的翻译。

第二章 WDM驱动程序的基本结构

在第一章,我描述了Microsoft Windows XP和 Microsoft Windows 98/Me操作系统的基本架构。解释了驱动程序的目的是管理一块代表系统的硬件,并且还讨论了如何决定你的系统会需要什么样的驱动程序。在这章里,我将更 加具体地描述WDM驱动的程序代码和各种在一起管理硬件的驱动程序的不同。还会引出系统是如何找到并装载驱动的。

一 个不错的理解完整的驱动程序的方式是将其想象成是一个收集让操作系统调用的用来执行各种涉及到你硬件操作的子程序的容器。图2-1说明了这一概念。一些程 序,如DriverEntry和AddDevice程序和一些类型的I/O 请求包(IRP)派遣函数会出现在每个这样的容器中。需要队列请求的驱动程序可能还有一个StartIo程序。而执行直接存储器存取(DMA)操作的驱动 程序会有一个AdapterControl程序。产生硬件中断的驱动程序也会有一个中断服务程序(ISR)和一个延期程序调用(DPC)程序。多数的程序 会有除了在图2-1中列出的三个之外的一些IRP种类的派遣函数。因此,若你作为WDM驱动程序的编写者,你则需要选择相应函数到你具体的容器中。

 图2-1被看成是子程序包的驱动模型

在本章中,我将给你演示如何编写一个单功能驱动的DriverEntry和AddDevice程序,这类驱动是本书要讨 论的内容之一。在后面的章节中你还会发现filter驱动也有类似的DriverEntry和AddDevice程序,而minidriver则有着很不 同的DriverEntry程序,并完全根据相关类别的驱动程序的作者来设计相应的驱动接口以决定是否采用AddDevice程序。

和应用于应用程序的“主程序和辅助程序”模型相比,我们值得想一下驱动程序的“子程序包”模型的含义。看看这个程序,这 是我们大多数开始编程序的时候写的:

 这个程序由一个名叫main的主程序和一个多数时候我们不明确调用的辅助程序库组成,如printf,其给一个标准输 出文件输出了一个消息。在编译完包含主程序的原始程序之后,将结果与一个含有printf等主程序所需要的辅助程序运行时库连接在一起,最后以一个可执行 模块告终,譬如HELLO.EXE。其和现在或之后的应用程序大体相同,所以我只要直接通过该应用程序的名字就可以调用它, 可以用如下方法调用这个程序:

 关于应用程序还有一些其他共通点:

其他的辅助程序是从系统的动态链接库(DLL)上被动态链接的。对于这些程序,链接器将专用的引入表放入到可执行文件文 件中,并且最终运行时装载器将这些参考地址修正令其指向真正的系统代码。实际上,由应用程序使用的整个Win32 API都是被动态链接的,所以你能看到动态链接在Windows编程中是一个非常重要的概念。

n         可执行文件也可以包含资源数据,如对话框模板,文本串,和版本信息。在文件内部的这种形式的数据比使用单独的辅助文件的效果要好,因为这可以避免存在不匹 配文件的问题。

有意思的是,就如HELLO.EXE这样的程序一旦操作系统把控制权给它。它直到其完全结束完它要执行的任务之后才会返 回。实际上这是你用过的所有Windows应用程序的一个特征。在就像HELLO.EXE这样的控制台模式应用程序下,操作系统最初将控制全转给一个初始 化函数,这个函数是编译器运行时库的一部分。该初始化函数最终调用mian程序来完成应用程序的工作。

Windows的图形化应用程序的工作方式同理,只不过主程序名称用WinMain代替了main。WinMain操作 一个消息队列用来接收和派遣窗口程序的消息。当用户关闭主窗口时其返回操作系统。如果你曾经只用MFC(Micorsoft Foundation Classes)构造过Windows应用程序,你会发现没有WinMain程序。实际上WinMain程序是被隐藏到了一个你绝不会找到的一个库中了, 可以肯定,它是确实存在的。

即使在一台只有一个CPU的计算机上也可以有多个应用程序被同时运行。操作系统的核心含有一个调度程序可以给当前符合条 件的线程运行一小段时间(这被称为时间片)。一个应用程序由一单线程开始并且如果它需要,还创建更多的线程。每个线程有系统给予的优先级优先级,并且根据 不同情况还会被调节,在每次调节时,调度程序会选出优先级最高的符合条件的线程,并把一系列的被保存的寄存器映象,包括指令指示器(IP)装载给处理器的 寄存器,通过这种方式把控制权给它。伴随着线程的时间片失效,处理器中断。作为处理中断的一部分,系统会保存当前寄存器的状态。这样当下次还是这个线程被 执行的时候,它的状态还可以被恢复。

    一个线程不止是只等待时间片的过期,它还可以在别的线程里阻塞其耗时的行为,直到这个行为结束。这比轮流等待完成的方式要好,因为若系统不得不靠一个时间 片的过期才能将注意力转移到别的线程上来的话,这样做则允许其他线程运行的比它们预计的要快。

    现在你应该明白我所说的了吧。我集中描述了应用程序运行的实质。在底层,一个线程的过程包括获取CPU资源,尝试挂起直到其退出。而操作系统调度程序则像 扮演了一个运动场监管者来让各自的线程在一起很好地比赛。

    就像HELLO.EXE程序一样,驱动程序也是可执行文件。其扩展名为.SYS,但在结构上严格地说这文件和任何32位的Windows或者控制台模式的 应用程序没什么区别。和HELLO.EXE程序一样,一个驱动程序也需要许多辅助程序,许多也都是动态链接自操作系统内核或来自一组驱动或者时其他的支持 库。当然,一个驱动程序文件也可以有调试信息和资源数据。

但是不像HELLO.EXE程序的是,驱动程序没有主程序。取而代之的是其包含了一批系统可以在适当的时候调用的子程序 集。固然,这些子程序还可以在驱动程序中,静态库中,和操作系统中使用辅助子程序,但驱动程序除了其其自己的硬件外没有照管任何别的事情:系统管理了其他 的任何事务,包括决定在何时运行你的驱动程序代码。

如下是一个关于操作系统会如何调用你驱动里的子程序的简要过程:

1. 用户装入了你的设备,这样系统就会装载你的可执行的驱动程序到虚拟内存中并且调用你的DriverEntry程 序。DriveEntry做了一些操作之后返回了。

3. 即插即用管理器发送给你一些IRP,你的派遣函数依次处理每一个IRP之后返回。

4.  一个应用程序打开了一个你的设备的句柄,因此系统发送给你另一个IRP,你的派遣程序做了少量操作之后返回。

5. 应用程序尝试读取一些数据,因此系统发送给你一个IRP,你的派遣程序将IRP放入一个队列之后返回。

6. 一个之前的I/O操作被一个你驱动连接到的硬件中断结束。你的中断程序做一些很少的操作,制定一个DPC,之后返 回。

7. 你的DPC程序运行了,在其他的事务中,它从第五条中的IRP队列中移除了IRP并安排你的硬件读取数据。之后 DPC程序返回系统。

8. 随着时间变化,在这期间系统会对你的子程序有许多简短地调用

9. 最后,最终用户卸掉了你地设备。即插即用管理器发送给你一些IRP,由你进行处理并返回,操作系统调用你地 DriverUnload程序,完成相当数量的细微操作之后返回。然后系统将你的驱动程序代码移出虚拟内存。

在过程中的每一步,由系统来决定你的驱动需要做哪些事情,将其初始化,处理IRP,处理中断,或者什么。因而系统在你的 驱动程序中挑选适当的子程序。之后你的子程序会做相应的操作之后返回系统。

驱动程序和应用程序的另外一个不同是运行驱动程序时系统并不创建专门的线程。取而代之的则是当某一个线程被激活的时候由 系统来决定是否执行驱动程序里的子程序

    当一个硬件中断发生的时候我们不可能预测到此时正是哪个线程。同样,想象一下你在游乐园正在观察旋转木马。其上的木马就类似于系统中的线程,我们将离你最 近的木马称为当前线程。现在我们假设当你无意中听到有人说“That’s awesome, dude.”时你决定用你的相机拍照(在我游乐园的经验中,这不会有长时间的等待),你不能预测到在你的快照中哪只马是当前的。当硬件发生中断的时候哪个 线程正在执行中也是不可预测的。我们称其为任意线程,我们所说的都是一个任意线程。

    当系统决定调用你驱动程序中的子程序时,它常常运行着一个任意线程上下文。线程的上下文会是任意的——例如,当你的中断服务程序获得控制权。如果你制定一 个DPC,那么运行你DPC程序的那个线程将会是任意的。如果你排队等待IRP,你的StartIo程序会被一个任意线程调用。事实上,如果一些在你的堆 栈外驱动程序发送给你一个IRP,你也不得不假设线程上下文是任意的。这通常会是给存储驱动程序的场合,因为一个文件系统驱动程序会成为对读写负责的代 理。

    系统不总是在任意线程上下文中执行驱动程序代码。一个驱动程序可以通过调用PsCreateSystemThread函数来创建自己的系统线程。驱动程序 也可以让系统在有相关操作项目的系统线程中回调它。在这些情况下,我们认为线程上下文不是任意的。我将在第14章讨论系统线程的结构和工作项目。

    不是任意的进程上下文的另一种情况发生在当应用程序放出一个了引起I/O管理器直接给驱动程序发送IRP的API调用时。你能知道你处理的每一个IRP是 否和你写的驱动有关

有两个理由让你关心进程上下文是否是任意的。首先,驱动程序不应该阻塞任意线程;虽然你激活了一些其他的线程,但是这不 公平。

第二个理由是当驱动程序创建了一IRP,并将其发送给一些其它的驱动程序。我会在第五章充分讨论,虽然你需要在一任意线 程中创建一种IRP(异步IRP),但你可能却在非任意的线程内创建了不同种类的IRP(同步IRP)。I/O管理器将同步种类的IRP连接到你创建 IRP的线程上。若该线程结束了其也会自动地删去IRP。但I/O管理器不将任何异步IRP连接到任何线程上,你创建的一个异步线程可能不会执行你要做的 任何I/O操作。并且由于线程的偶然终止还会导致系统取消IRP错误。所以其不行。

 均衡多处理技术

Windows XP使用了一种所谓的均衡模型来管理多处理器的计算机在这种模型下,每一个CPU像所有其他涉及线程调度地CPU一样被严格地处理。每个CPU豆科一拥有 其自己的线程。这可能对I/O管理器,在两个或更多的CPU上执行线程的上下文,同时调用你驱动中的子程序来说是完美的,我没有说那种运行在单CPU上的 线程的那种假同时,这些线程只能同时被运行一个,并根据时间来轮换。而一个多处理的机器不同的线程则可真正地被同时执行。你可以想象,这种同时执行使驱动 对共享数据的同步访问有着严格的要求。在第四章里我将会讨论你可以用于此目的的不同的同步方法。

2.2系统如何找到并装载驱动


我在前面的部分强调了操作系统是如何全面负责计算机并访问设备驱动程序来做一些有关硬件的操作。驱动程序在使其 被首先加载的处理中扮演一个同样被动的角色。如果你很快就能明白系统是如何发现硬件,确定装载哪些驱动程序,和配置驱动程序来管理硬件的话,那么这将有助 于你了解本书的其他内容。系统使用了两种稍微不同的方法,这依赖于硬件是否具有即插即用的兼容性。

n         即插即用设备有一个系统可以发现的电子签名。对于即插即用设备,系统总线驱动程序将发现其是否存在,并且读取这个签名来判定它是哪种硬件。随后一个基于注 册表和INF文件的自动处理保证了系统可以正确地加载驱动。

n         一个非即插即用的设备则没有这个电子签名,所以系统不能自动地发现它。最终用户因此必须通过调用添加新硬件向导来启动“探测”处理,最终系统发现了新硬件 的存在。其后系统用和即插即用同样的方法自动处理注册表和INF文件保证了系统可以正确地加载驱动。

无论系统使用哪一种方法来发现硬件并装载驱动,该驱动程序自身都将会成为一个被操作系统被动调用的WDM驱动。在这一点 上,WDM驱动与Windows NT早期版本的内核模式驱动和Windows 95之前的VxD驱动形成了鲜明的对比。在那些环境里,你必须用某些方法来让系统装载你的驱动。该驱动之后会扫描硬件总线来查找它自己的硬件并决定是否常 驻内存。另外,你的驱动程序还不得不得确定使用那些I/O资源,并设法阻止其他驱动占有同样的资源。

设备和驱动程序的层次结构

在搞清发现硬件和驱动程序装载的过程之前,我需要说明图2-2中驱动程序的层次结构的概念。如图2-2所示,左列描述了 一个向上链接的使用内核DEVICE_OBJECT结构的栈。涉及到系统是如何管理一块单一硬件的。中间的这列显示了扮演管理角色的设备驱动集。右边那一 列阐述了一个IRP通过驱动程序的流程。

图2-2 WDM中的设备对象和驱动程序的层次结构

在WDM中,每一个硬件设备至少有两个设备驱动。其中一个我们称之为功能驱动,这是你最关心的设备驱动。它了解使硬件如 何工作的所有细节。它负责初始化I/O操作,处理发生在这些操作完成时的中断。并且给最终用户提供一个方法来适当的演练控制硬件。

一个单独的WDM功能驱动是一个动态链接到包含操作系统内核和的HAL.DLL(其包含有系统抽象层(HAL))的 NTOSSKRNL.EXE的单一可执行文件,一个功能驱动也可以动态链接到其他内核模式的DLL。微软已经给你的硬件类型提供给了类驱动程序,在这种情 况下,你的迷你驱动(minidriver)会动态链接到类驱动程序上。迷你类驱动和这类驱动联合组成了功能驱动程序。你会看到调用类驱动于小类驱动之上 之下的类似的事情。我更关心这些所谓的“类”驱动作为独立的过滤器驱动并对相关的迷你驱动的驱动单独地使用规则类驱动,通过明确的外在的引入,使迷你驱动 自动地发挥。

我们调用另一个驱动是每个设备都要有的总线驱动。其负责管理硬件与计算机的连接。例如对于周边元件扩展接口 (PCI)总线的总线驱动的就是用来探测你的板卡是否被插入到了PCI槽上并来确定你的板卡对于I/O映像或存储映像的需求的软件组件。其还是开关电流到 你板卡上的流程的软件。

    一些设备有两个以上的驱动程序。我们用一般规则过滤器驱动来描绘这些驱动。一些过滤器驱动简单地监视作为功能驱动完成IO任务。经常一个软件或硬件供应商 会提供过滤器驱动来在某些方面修改存在的功能驱动程序的行为。上层过滤器驱动程序在功能驱动之前获得IRP,并且其有机会支持驱动程序不了解的额外的方 面。有时上层过滤器驱动能够针对在功能驱动或硬件上的Bug来执行一工作区。而下层驱动程序获得的是功能驱动程序尝试发送给总线驱动前的IRP 。(一个下层过滤器驱动在栈里位于功能驱动之下而在总线驱动之上)。在一些情况下,如当设备是附加于通用串行总线(USB)的,下层过滤器是可以修改功能 驱动程序试图执行的总线操作流的。

    我们再看一下图2-2,注意这四个驱动程序中的每一个都被显示为一假定的连接到左侧DEVICE_OBJECT结构的设备。这些结构中的缩写是:

n         FiDO代表过滤器设备对象。过滤器驱动程序使用这一对象作为存储其需要保存的关于硬件和其的过滤行为的地方。(早先释放的Beta版的Windows 2000 DDK用了规则FiDO,当时我采纳了它。DDK不在使用这规则,据我猜测,它被认为太轻佻了。)

我恰当地使用了规则总线和总线驱动程序但没有说明其是什么意思。对于WDM的目的,总线是你可以插入设备的任何东西,而 不是物理上或者比喻上的。

我想这是一个恰当的而广泛的定义。其不止包括如PCI总线,还包括小型机算计系统接口(SCSI)适配器,并行端口,串 行端口,USB集线器等等的任何东西。事实上只要他能让另一个设备插上去。

这一定义还包括了一我虚构出来的根总线。用来关心所有非即插即用的设备。这样,根总线就是非即插即用工业标准结构 (ISA)板卡或连接到串行端口但不使用标准的辨认串来答复串行端口列举信号的智能卡读卡机的双亲。我们也可以认为根总线是PCI总线的双亲——这是因为 PCI总线并不自我告知其物理存在,因此操作系统只能将其识别为非即插即用设备。

再重复一次我之前所说,即插即用设备是一种拥有能使总线获悉设备身份的电子签名的设备。如下是这些签名的一些例子:

对于即插即用总线的总线驱动程序有能力通过在启动时扫描所有可能的插槽来列举其总线。对于热插拔设备(如USB和 PCMCIA)总线的驱动,它们还要监测是否还有新的设备到来的硬件信号,因此驱动程序还要再次列举其总线。最后的结果就是列举或者再列举处理成为了一 PDO集。如图2-3①。

图2-3 安装即插即用设备

    当总线驱动程序检测到硬件的增删,其会调用IoInvalidateDeviceRelations来告知给即插即用管理器(PnP Manager)总线上孩子设备的数量已经改变。即插即用管理器发送一IRP给总线驱动来获得关于孩子设备的最新PDO。这个IRP的主功能代码是

每一个IRP都有主/辅功能代码。主功能代码指出IRP包含什么类型的请求。IRP_M3_PNP是适用于即插即用管理 器生成的请求的主功能代码。就主功能代码而言(包括IRP_M3_PNP),辅功能代码被用来说明更详细的操作。

为相应总线关系查询,该总线驱动程序返回其PDO列表。即插即用管理器可以轻松地确定哪些PDO代表它未初始化的设备。 让我们集中注意力在你硬件的PDO上,看看接下来会发生什么。

即插即用管理器会发送另一个IRP给总线驱动,这次是辅功能代码IRP_MN_QUERY_ID。如图2-3③。事实上 即插即用管理器会发送几个这样的IRP,每一个都有一令总线驱动返回一标识符类型的操作数。其中一个操作数的设备标识符唯一指定了设备的类型。设备标识符 是像如下例子中的串:

每个总线驱动程序有其自己的收集入标识符串的用于格式化电子信号信息的架构。我将会在第15章讨论被用于通用总线驱动的 标识符串。那章也是查找关于INF文件和被以文本模式描述在注册表层次中的注册表键值并在注册表中保存为何类信息的地方。

    即插即用管理器用硬件标识符来定位在注册表中的硬件键值。目前,让我们假设你的驱动是第一次被插入到计算机中。如果是那样的话,还不会有对于你的硬件的类 型的键值。此时安装子系统会帮助找到哪些软件适合你的驱动。(请看图2-3④)

对于所有硬件类型的安装指令存在于扩展名为.INF的文件中。在每一个INF文件中有一个或多个样式声明包含相关的用于 安装的详细设备标识串的节。对于一个崭新的硬件,安装子系统会试图从相关的INF文件中找到何硬件标识符匹配的样式声明。提供这些INF文件就是你的责任 了,这就是为什么我在图中将这一步指向你。我在指出系统是如何搜索INF文件和将这些其很可能找的样式声明说的含糊一些。我将在第15章具体说明,现在讨 论这些还是有点深的。

当安装子程序找到了正确的样式声明,其会执行你 在安装节中提供的指令。这些指令可能会包括在最终用户的硬盘上复制一些文件,在注册表中定义的一个新的驱动服务等等 。在处理的最后安装程序会在注册表中创建硬件键值并安装你提供的所有的软件。

现在回到上面几段,假如现在不是第一次在相关电脑上安装你的硬件。例如我们谈论的USB设备已经被用户移除,现在用户要 将其再插入到系统上。如果是这样的话,即插即用管理器会找到相应的硬件键值,并不需要调用安装程序。因此即插即用管理器将跳过安装处理直接到图2-3⑤。

这里,即插即用管理器能认出存在你的驱动程序负责的设备。若你的驱动程序还没有被载入虚拟内存,即插即用管理器会调用内 存管理器来映像之。系统没有将你驱动器上的磁盘文件直接读取入内存。取而代之的是其创建了可令驱动程序代码被分页I/O获取的文件映像。除了其有当你允许 你的驱动被清出映像时的令你小心的后遗症外,实际上系统使用了文件映像并不会影响你太多。这样内存管理器之后会调用你的DriveEntry程序。

接下来即插即用管理器调用AddDevie程序会告知你的驱动程序有一新的设备被发现。(如图2-3⑤)。其后即插即用 管理器会发送一辅功能代码为IRP_MN_QUERY_RESOURCE_REQUIREMENTS的IRP给总线驱动。该IRP主要是请求总线驱动来描 述你的设备对于中断请求线, I/O端口地址, I/O内存地址,和系统DMA通道的需求。该总线驱动会构建这些资源需求的列表并将其传达。(如图2-3⑥)

最终,即插即用管理器即将配置硬件。其会令一资源分配器给你的设备分配资源。如果这些都做完了,即插即用管理器就会用辅 功能代码IRP_MN_START_DEVICE发送IRP_MJ_PNP给你的驱动。你的驱动会通过配置和连接不同的内核资源来处理该IRP,之后你的 硬件即将使用。

文中描述了Windows XP(当然还有Windows 2000,Windows 95,核Windows 95的所有后续版本)是如何查找并要求驱动是相对被动的装载的过程。但Windows NT 4.0以及之前的版本却处理的很不同。在这些系统中,你已经提供了某些用来安装你驱动的安装程序。你的安装程序会更改注册表来保证其在下一次重启德时候会 被装载。这样,系统会装子你的驱动程序并调用DriveEntry程序。

你的DriveEntry程序会以某种方法来检测你的那些硬件实例是真正地存在。你可能会扫描所有PCI总线的插槽,例 如,还是假定你设备的每一个实例符合注册表中的子串。

发现完你的硬件之后,你的DriveEntry程序会继续指派和存储I/O资源并做现在WDM驱动程序做的配置和连接的 步骤。如你所见,因此WDM驱动程序比之前版本的Windows NT的驱动程序有更少的启动工作。

我用术语 legacydevice来描述任何不支持即插即用的设备,这意味着系统不能自动检测到其的存在。让我们假设你的设备在这其中。用户买到你的设备后,其首 先会调用添加新硬件向导之后会做一系列的对话框选择来将安装程序引导到一INF文件中的安装节。(如图2-1①)

图2-4 一非即插即用设备的发现过程。

安装程序根据在安装节中的命令用列举器创建注册表入口(如图2-1②)。该注册表入口可能包括一逻辑配置,其列出了设备 I/O资源请求(如图2-1③)。

最终,安装程序会通知最终用户重新启动系统(如图2-1④)。安装系统的设计者希望最终用户此时应按照厂商的使用说明通 过设定跳线或开关来配置你的板卡,并希望在系统关机的情况下将其插入扩充插槽。

在重启动之后(或按最终用户的要求绕开充启),根列举器会扫描注册表,并找到新添加的设备。其后,装载你的驱动的过程和 即插即用设备的一样。如图2-5

大多数的驱动程序的例子对应的内容都是虚假的硬件,你将其作为非即插即用设备(不存在的)硬件来安装。例子中的一两个对 I/O端口和中断起作用。各自的INF文件包含有记录配置的节使即插即用管理器分配这些资源。如果你通过添加新硬件向导来安装这些驱动中的一个,系统会认 为这需要一个断电重启,但实际上你并不需要充启。

图2-5 装载一非即插即用驱动程序。

    在之前的部分中,我描述了对于一单独的设备,系统是如何装载正确的驱动的。这一描述提出了一个问题:系统是如何在计算机中设法装载所有硬件的驱动的?答案 是:其使用递归列举。

在第一个例子中,即插即用管理器调用根列举器来查找其不能电子地宣布其存在的所有硬件——包括主硬件总线(如PCI)。 根总线驱动程序从注册表中获取被Windows XP安装程序初始化了的计算机信息。安装通过运行一详细的硬件检测程序和向用户询问适当的问题来获取信息。因此,根总线驱动程序就有了足够的信息来给主总 线创建PDO。

主总线的功能驱动之后可以电子地列举其自己的硬件。当总线驱动列举硬件时,其扮演为一普通的功能驱动。然而在发现新硬件 后,该驱动程序则转变了角色:它成为了总线驱动,并给新发现的硬件创建新的PDO。即插即用管理器之后就和以前讨论过的一样为这个设备PDO装载驱动程 序。对于设备的功能驱动程序还可能列举出更多的硬件,这种情况下,整个过程是重复递归的。最终的结果会像是图2-6中所示的树结构:其中,一总线设备栈分 支到附加到该总线上的硬件的其他设备栈。图中深色框代表一个驱动程序可以戴多少顶“FDO帽子”来扮演对于其硬件的功能驱动,多少顶“PDO帽子”来扮演 附加设备的总线驱动。


图2-6递归列举设备层次

我一开始说过设备可以拥有上层和下层过滤器驱动和功能驱动程序。有两个和设备关联的注册表键值包含了过滤器驱动的信息。 包含有你硬件实例的信息的device键可以有给该实例指定过滤器驱动的UpperFilters和LowerFilters值。另一个注册表键值记录了 设备是属于什么类(class键)的。例如,鼠标属于鼠标类,这样不用我说你就应该明白了吧?class键也可以包含UpperFilters和 LowerFilters值。其指定了系统会为每一个属于该类的设备装载的过滤器驱动。

    了解系统调用驱动的顺序在某些时候可能是很重要的。装载驱动的实际过程必须要让驱动代码映像到虚拟内存中,这个顺序并不值得关注。但你应该关注在不同的驱 动程序中调用AddDevice函数的顺序。(请参照图2-7)

你也许已经注意到了属于类和不作为你所期望的纯嵌套的设备实例的上/下层过滤器的装载问题了。在我知道事实之前,我猜设 备级别的过滤器可能比类级别的过滤器更接近于功能驱动程序。

在WDM中驱动的正式分层使IRP以可预言的方式从一个驱动向另一个驱动的传递变得很容易。图2-2阐述了大体的思路: 只要系统打算在一个设备上实现一个操作,其会给在栈中最高的过滤器驱动发送IRP。驱动程序可以决定是处理该IRP,还是将IRP传递给下一级别,或是两 者皆做。每一个留意IRP的驱动都进行同样的动作。最后IRP可能会在其的PDO角色中到达总线驱动。尽管图2-6似乎还在暗示什么,但等其到了总线驱动 一般就不会再传递IRP了。相反总线驱动通常结束该IRP。在一些情况下,总线驱动会将同样的IRP传递给扮演FDO角色的栈(双亲驱动栈)。在其他情况 下,总线驱动程序会创建一二级IRP并将其传递给双亲驱动栈。

我会在本章稍后的地方说明DEVICE_OBJECT数据结构。不透明的字段AttachedDevice将设备对象链 接到栈顶。以PDO为开始,每一个设备对象立刻指向了其上的对象。不能证明向下的指针——……(事实 上,IoAttachDeviceToDeviceStack在一DDK没有全部生命的结构中建立了一向下的指针。对于逆向工程来说这是不明智的因为其会 再任何时候被改变。)

AttachedDevice字段故意没有被证明是因为其适当的使用需要同步的可能会将设备从内存中删除的代码。我们被 允许通过调用IoGetAttachedDeviceReference来找到栈中顶端的设备对象。该函数还会添加一参考计数来防止对象被过早的移出内 存。如果你打算使你下至PDO的方式运转,你应该以辅功能代码IRP_MN_QUERY_DEVICE_RELATIONS和类型参数 TargetDeviceRelation发送给你一IRP_MJ_PNP请求。PDO驱动会通过返回PDO的地址来响应。当你第一次创建设备驱动时,由 于只需要记住PDO地址,这会很简单。

类似的,若想立即获悉哪个设备对象在你之下,你需要保存你第一次添加你的对象到栈中的地址。既然在栈中的每一个驱动程序 会有其自己未知的用IRP派遣来实现向下指针的方式,那么这样,一旦栈被创建,就不能被更改了。

一些例子会阐明FiDO、FDO和PDO之间的关系。第一个例子涉及到在通过PCI到PCI桥接芯片将自己放在主总线上 的二级PCI总线上的设备的读取操作。简单起见,让我们假设存在一个适合于此设备的FiDO,如图2-8所述。在之后的章节中你会学到一个读请求通过以主 功能代码IRP_MJ_READ变成IRP。这样的请求会首先流动到上层FiDO之后流到设备的功能驱动。(该驱动就是被标记在图中FDOdev中的设备 对象的驱动。)功能驱动程序直接调用HAL来执行其功能,所以图中没有其他驱动程序能够注意到IRP

图2-8 对于在二级总线上设备的读请求流程。

修改一下第一个例子,其结果显示在图2-9中。现在对于插到一个其本身被插到主机上的USB HUB上的设备,我们有一个读请求。对于Hub和主机来说,全部的设备树因此包含设备栈。IRP_MJ_READ穿过FiDO到了功能驱动,功能驱动之后 发送一个或更多不同种类的向下到其自己PDO的IRP。适用于USB设备的PDO驱动是USBHUB.SYS,并且其将IRP运送到主机设备栈中的顶端的 驱动,跳过了USB hub的两个驱动栈。如图中部所示。

图2-9 对于USB设备的读请求流程。

第三个例子除了正被讨论的IRP是一个关于是否PCI总线上的磁盘驱动器会作为系统分页文件的存储地点的通知以外,其他 的都和第一个例子类似。你会在第六章学到该通知用辅功能代码IRP_MN_DEVICE_USAGE_NOTIFICATION表现为一 IRP_MJ_PHP请求的形式。此时FiDO驱动程序传递请求给注意到它的并会将其传递给栈中更下方的PDOdev驱动的FDOdev驱动。此特殊的通 知还引出了其他关于即插即用系统或电源管理的I/O请求是如何被处理的。所以PDOdev驱动给在FDO总线内部的栈发送同一通知。如图2-10。(并非 所有的总线驱动都以这种方式工作,但PCI总线确是)

图2-10 设备用法通知的流程

更好的形象化设备对象和驱动程序的方式是分层,在这里工具是有助于你的。我写了DEVVIEW工具,在附加内容中你会找 到它。用第十二章中插入到二级USB Hub上的USB42的例子来说,我运行了DEVVIEW并在截了两个图(如图2-11和2-12)。

此设备只用了两个设备对象。PDO被USBHUB.SYS管理,而FDO被USB42管理。在第一张截图中,你可以看到 关于PDO的其他信息。

值得在你自己的系统上试验一下DEVVIEW来看看你自己的硬件有多少不同的驱动被分层了。

2.3两个基本的数据结构

    这部分(内容)(主要)讨论两个最基本的有关WMD驱动程序的数据结构:驱动实体和硬件实体。驱动实体指的是驱动(程序)自身以及所有驱动子程序指针 ----系统将在运行时调用这些子程序。归根结底,你应该明确:你在自己的驱动程序中经常提供的指向日常(命令)的指针,(在系统中)是作为各种内核服务 请求中的中断(命令)的。硬件实体指的是一个硬件实例及其包含的有关帮助用户操作该硬件的数据。

    I/O管理使用一个驱动实体数据结构来表征每一个硬件实体。(参看2-13。)类似我们讨论的许多数据结构一样,驱动实体是半透明的。这就是说,你和我有 可能直接访问或者修改的仅仅是数据机构中的特定文件,即使DDK的头文件声明了全部的(数据)结构。我曾经展示过灰色背景数字中驱动实体的半透明文件。这 些半透明文件类似于C++类中的私有成员和受保护成员,同样允许访问的文件类似于公有成员。
    DDK的头文件按照一种模式方法(来)声明驱动实体,并且所有其他核心模式数据结构(也)针对这个问题,如同如下从WDM.H(文件)中摘录(部分)说 明:

这段代码的含义:开头声明一个类型名为:DRIVER_OBJECT的结构体。它同时还声明了一个指针类型(PDRIVER_OBJET)并且分配 了一个结构标签(_DRIBER_OBJECT),这种申明类型出现在DDK中的很多地方,因此我以后将不再提起。头文件还声明了一个类型名的小设置(比 如CSHORT)以便描述在内核模式中使用的原子数据类型。举个例子,CSHORT的意思是:带符号的短整型(数据)作为基本数据来使用。
表 2-1列出了一些这样的名称:

表2-1.常用内核驱动的类型名

有关64位类型的说明:DDk头文件包括类型名是为了驱动程序作者能够较方便的在Intel平台上编辑相同的源代码----无论32 位的还是64位的。举个例子来说,不妨假设一个长整型的数值和一个指针具有相同的字长,你需要声明的变量肯能既不是一个LONG_PRO也不是一个 ULONG_PTR。像这样的变量可以是一个长(或者无符号长)(整型)或者一个指针什么的。同样的,例如,使用SIZE_T类型来声明一个整型数据可以 具有同指针相同跨度的字长----你可以在64位平台上得到一个64位的整型数据。在DDK头文件中类似的和其他的32或64位定义类型被命名为 BASETSD.H文件。

现在我将简述驱动实体中可以使用的文件。

DeviceObject(PDEVICE_OBJECT)是位于硬件实体列表中的数据结构,任何一个硬件都是由驱动程序来配置的。I/O管理将驱 动实体及其维护文件联结成一个整体。一个非WDM驱动程序的DriverUnload(驱动卸载)函数将用来作为切断驱动实体和(硬件实体)列表联系的文 件,以便(从列表中)删除他们。一个WDM驱动程序很可能没有任何特别的需要来使用这些文件。

DriverExtension(PDRIVER_EXTENSION)(驱动扩展部分)指向一个微小的精简结构,它包含在那些仅仅添加硬件成员可 以使用的部分。(参看2-14)添加硬件是一个指针:指向在驱动中创建硬件实体的函数;这个函数具有相当大的分量,在本章之后的一段“添加硬件”段落我将 用较大篇幅谈论这个部分。

    硬件数据库(PUNICODE_STRING)作为一个字符串命名为一个“对于硬件的硬件数据库注册表关键字”。这是一个类似于:注册表,机器,硬盘,界 面,系统;而且在注册表关键字中包含了资源分配信息属性。WDM驱动程序无需通过这种关键字中信息的(确认),因为PnP管理自行执行资源分配。名字存储 在独立的代码中。(事实上,所有的内核字符串数据都是用独立代码。)在下一章,我将讨论UNICODE_STRING独立代码字符串树蕨结构的格式和使用 (情况)。
    最快I/O管理(PFAST_IO_DISPATCH)指向一组函数指针----文件系统和网络驱动出口。这些函数如何使用已经超出了这本书(讨论的)范 围。如果你有兴趣学习更多有关文件系统驱动的内容,请查阅Rajeev Nagar的视窗NT文件系统探秘----一个开发指南(O'Reilly及其同事著,1997)。
    驱动起始I/O(PDRIVER_STARTIO)指向你的驱动中的一个函数:I/O进程请求----I/O管理已经分配给你的(资源)。在第5章我将大 概讨论有关请求队列以及这种特例中的作用。

    驱动卸载(PDRIVER_UNLOAD)指向驱动程序中的清除函数。我将讨论这个函数与驱动载入之间的联系的一些联系,但是你可能也知道现在一个WDM 驱动程序很可能无论如何也不需要任何有意义的清除。

    主函数(PDRIVER_DISPATCH队列)是一组驱动中的指针函数:涉及大概将近20多种I/O请求的每一种。如你所料,这组(指针)也占有很重的 分量,因为它定义了在你的代码中I/O请求是如何实现的。

    2-15节说明了硬件实体的格式以及在隐含文件中的隐藏条件的使用,这些问题,我在先前驱动实体的讨论中曾经用过。作为一个WDM驱动的作者,你将通过调 用IOCreateDevice(I/O创建实体)来创建很多类似的实体。

    下个实体(PDEVICE_OBJECT)指向的下一个实体是一个属于相同的驱动程序并且类似这个(实体)的实体。这个文件是将所有硬件实体从一开始就以 驱动实体的“驱动实体成员”联系在一起的。很可能没有原因让一个WDM驱动程序来使用这个文件。或许仅仅因为使用这个指针(可以)要求同步使用一个系统内

2-15节.硬件实体数据结构
    通用中断请求(PIRP)是微软中断请求队列中“起始包”和“起始后继包”常常用来记录最近发送给你的起始I/O内容。WDM驱动应该遵循她自己的IRP 队列(参看第5章)并且无须使用这些文件。

    特性(ULONG)是另一个标志位的集合,定义成各种各样可选择的设备特性。(参看表2-3)I/O管理根据IOCreateDevice的争端来初始化 这些标志位。过滤器驱动把其中的一些标志位向设备栈的上方传播。

(参看16章内容:有关过滤器驱动的详细讨论以及更多的有关标志(位)上传的信息。)

设备扩展(PVOID)指向的数据结构:对于设备你定义的将出现在每个实例信息中的部分。I/O管理为这个结构分配空间,但是他的名称及内容完全取 决于你。一个常用的方法是声明一个类型名为DEVICE_EXTENSION的结构体。为了访问给定的设备指针(例如:FDO),使用如下的声明:

它很快将成为现实(现在或者什么时候):紧随着设备实体,设备扩展部分即刻出现在内存中。但是依赖于这种通常出现的情况也可能不是个好主意:尤其是 当记录方法紧随DeviceExtension指针而持续工作的时候.

设备种类(DEVICE_TYPE)是一个标示:通常用来表明这个设备是什么类型的.I/O管理基于I/OCreateDevice(提供的)争端 来初始化这个成员.过滤器驱动程序可能确实需要检查这项内容。在这次写操作的时候,对这个成员有超过50种可能的评估。来确定DDK文件是否可以进入列表 中的MSDN内容的“硬件类型详细清单”。

栈长(CCHAR)包含的数目是:硬件实体从开始第一个递减到最后一个PDO的(总数)。这个文件的目的是要确定:首先对这个设备的驱动程序来说, 为一个IRP(中断请求)分配多少(内存单元),以便创建相关部分的栈内容。但是WDM驱动程序往往不需要修改这些值,因为底层程序自动生成这些设备栈 (I/OAttachDeviceToDcviceStack)。

值。(将字节、字的长度改为512个字节的代码)值仅仅转换成2减1。举个例子:代码0x3f是一个FILE_64_BYTE_ALIGNMENT. (64字节的数)

我要回帖

更多关于 芯片组驱动需要装吗 的文章

 

随机推荐