我一直认为,编写程序是一件很奇妙的事情,它可以带来创造和控制的欲望。每当我阅读或者编写一段代码时,脑子里自然地就会想象这段代码怎样完成预定的逻辑。对于代码编写者或者维护者来说,真正见功夫的地方不在于代码本身,而在于对下层开发平台的理解和驾驭能力,可能这就是俗称的“内功”,这个观点既适用于应用软件程序员,也适用于系统软件程序员。
本期门诊特邀AMD公司知名Windows内核驱动开发领域专家张佩先生,针对WDM\WDF框架、USB设备驱动、设备驱动安装等问题给予解答,欢迎网友积极提问,与专家一起讨论!
专家著作:《竹林蹊径:深入浅出Windows驱动开发》
本期门诊链接:http://doctor.51cto.com/develop-213.html
本期专家:
张佩
Q:324120
windows 内核驱动是个什么情况?代码吗? 像一般的那种比较难找的USB驱动是该怎么驱上去的呢?谢谢
A:张佩
驱动两个字是英文driver的翻译,料来是很达意的。打比方说,一辆汽车,你买车会综合考虑各种参数,驱动是发动机那一环,最基础和顶重要的。其次要考量一下外形或内部装修等,这就好像ui程序。开车的人一般不担心发动机会出故障,而更当心车漆不要被刮了这类问题。因为发动机不容易坏,果真坏了,车子就非常危险。 驱动程序也一样。你问驱动是代码吗?当然是了,只不过是顶重要和关键的代码,在内核环境中运行,负责处理用户程序请求。OS在内核中提供了很丰富的接口,用户程序永远无法使用它们,但Driver会仰赖它们来实现自己的各种功能。特别是和硬件交互。比如U盘读写,在用户程序而言,到Read\WriteFile就算结束了,殊不知在内核还有重重关口要过。说到底,驱动程序是NT内核的补充,它像打到砖墙里的钉子一样,被OS加载后,就成了和内核一体的了。内核关键而脆弱,能实现强大功能,也会不经然给个蓝屏。所以安全第一,次而功能。
Q:CHO尧子
张老师:
您好。首先,我想问的针对笔记本电脑的显卡驱动问题,为什么有时候无法安装显卡驱动,但是显卡并没有坏,在官网上也有驱动,型号是HP-CQ45,还有什么是WDM\WDF框架?我以前没有听说过呢!我还可以问下关于浏览器方面的问题么,有时候浏览器总是出现自动崩溃,没有病毒,网速正常,是什么原因导致的?
A:张佩
你好。显卡型号特别多,驱动安装需对号入座,这个号就是设备id。这个id是写在设备固件里面的,os读出这个id并寻找匹配的驱动进行安装。os很聪明,绝不会张冠李戴,所以你要说为什么驱动不能安装或更新,首先要确定你下载了正确的安装包。你要有本事,可以在安装包中找一找inf文件,看看它支持你的显卡否?可通过设备管理器查看你系统中显卡的设备id。 这二者必须匹配才行。可以把设备ID理解成设备在PC中的个人身份证,我们不能因为两块显卡是一家人(型号相同),而认为它们就是同一个人(设备ID可能不同)。
那么最后,我建议你懒一点,如果是win7系统的话,尝试在设备管理器中右键选更新驱动,并让它自己去网络服务器上搜索有无新版驱动,或能解决你的问题。
Q:leo0087
张大哥,您好:
小弟很想知道WINDOWS和LINUX内核有什么区别?
张佩
你的问题很像一个面试题。一般面试的时候他们都会问我:)我不懂linux啊。微软是庞大的软件帝国,你应该晓得,有两个截然不同的windows,一个是基于dos的win9x,一个是参照了dec的vms而开发出来的NT系统。现在用的是后者。
linux是类unix的操作系统,它大抵是一个孤愤之作,因为unix的版权所有者AT&t公司当时停止了unix的开源,并发起了一些诉讼官司。于是才有了linux和minix这类重造锅炉的类 unix系统。说到二者的区别,千差万别不为过吧。NT之父Cutler是满怀着对unix的无比鄙视和愤怒开发出NT系统的,你可想而知。前者unix 类大抵使用单一内核,而后者NT基本算微内核吧,这是最典型的差别。当然,单一内核或微内核,二者都并不纯粹,是互有参照的。
Q:zhang45xiang
您好:如同本期:如何正确入门Windows系统驱动开发领域 来说,如何进行系统驱动开发呢?当系统驱动存在冲突的时候如何解决,如何卸载干净?
A:张佩
入门对各行各业都不是一个简单回答的问题,请从基本做起吧,先熟悉起wdm/wdf这类基本框架,写一些简单的内核服务,演练起来,培养兴趣和基础。第二个问题,是不存在的。系统有自己选择驱动的机制,哪有冲突的可能。这要你熟悉inf文件才可,要熟悉系统是怎么选Driver的,这样你就不会困惑了。第三个问题,一言难尽呢。但就驱动程序而言,基本上只要在设备管理器中选择删除,它会把注册表中相关的服务键、枚举键删除的,inf目录中的 oemxx.inf也会删除,这就够了。失去这些信息,其他内容已不能工作。
Q:hagejid
买过一本天书夜读,不过里边介绍64位编程的内容太少了,不知道在64位下内核编程有什么要注意的地方。
A:张佩
朋友,竹林一书中关于64位编程的内容,已经免费放出来供下载,无数同学都在阅读了,你何不网上也找来一读?比我在这里费力地扯一两句要有用多。
Q:manchester1878
菜鸟求问,系统漏洞的分析是不是必须要深入理解内核
张佩
菜鸟兄,我劝你和我一样,暂且不要去分析系统漏洞了吧。那是很少一群人干的,靠那个能赚钱。你先不考虑吧,有空看起内核相关的一二本书,权当消遣,不是更好?
Q:baofeng1937
张老师:你好!
非常高兴见到你!很想知道WDM/WDF框架在WDM中操作系统与内核的交互式和在WDF中的二者分离,如何保证系统与硬件的兼容性?
A:张佩
WDM/WDF的问题,简而言之:WDF本质上是对wdm的封装。一个WDF驱动分成两个部分:WDK提供的基于WDM编写的WDF框架代码,和程序员基于此框架编写的自己的代码。
我先说前者WDF框架。WDF是基于WDM的封装,意思是说,微软WDK提供一个基于WDM的模板,在模板中完成基本代码,或者复杂而累赘,或者艰难而生僻的代码逻辑等等。这个模板就是名为WDF的框架,目前实现在文件wdf01000.sys中。再谈后者:框架有了,装修和细节还是要程序员自己来填充的,并且程序元需要根据定义好的框架来有序填充,这就是程序员自己的代码。二者拼在一起,是一份完整的WDM驱动代码。
理解了这种关系之后,我们就可以知道,WDM和WDF之间其实不存在任何兼容问题,只要系统中有WDF框架文件存在即可以了。
再讲两点:
1. WDM/WDF的关系,和前代两种框架VxM与WDM间的关系是不一样的,二者不互相兼容,因为WDM并不是基于VxM的封装,完全不同;
2. 国内熟悉MFC开发的人特多,可以类比,MFC框架是对Win32编程的封装,Win32/MFC的关系类同于WDM/WDF关系,你可以去想象。
Q:baofeng1937
张老师:
针对上面的usb驱动话题,我还想知道我们的移动存储设备、USB类的键盘鼠标等,通过与系统的连接,是不是基于系统中的USB驱动程序进行运行,而本身有没有装驱动?如果没有,那么类似u盘这类无法发现情况,是不是系统驱动的问题?如果有,那么它们又是怎样与系统驱动进行交互执行的呢?
A:张佩
所有连接到主机的外设,都是由驱动程序驱动的,我没有看到过特例。或者这样说:凡是连接到系统总线(ACPI/PCI)上的设备,都会被系统枚举并尝试安装驱动,无一例外。介绍你一个认识系统设备树的简单方法:命令行中敲入DevMgmt.msc命令,运行设备管理器程序;在View菜单中选择“依连接排序设备”;你能看到一个名称类似“X86 PC电脑”的根设备。展开这个设备后,就能看到一级级的子设备了。
另外,你问题里面提到的多种USB设备的驱动问题,答案非常简单:这些设备一定是有驱动程序的,当然这些驱动程序往往都不用你自己去手动安装,因为它们是普遍被使用的标准设备,微软OS早就为它们准备了In-Box驱动,这些驱动在你的OS被安装好后,就已经存在于系统目录中了,当设备首次接入后会自动安装这些In-Box驱动。另外,在这种情况下,这些标准USB设备的生产厂商也是可以编写自己的驱动来代替OS的In-Box驱动的,至于怎么代替,话题扯远了,这里不提。
Q:niceheart
张生,你好,请问一下windows内核具体怎么开发?windows 内核对计算机有哪些重要的作用?他的核心是什么?谢谢!
A:张佩
你提问中有三个问号,回答如下:
1. 我们这里只讨论驱动开发,无能讨论内核开发。
2. 你问内核对计算机有哪些重要作用。就像汽车,你说它座位以下部分对于这辆车子能够正常跑起来,起个什么作用?
什么是内核?内核就是OS本身!我们平时的桌面,只是一个壳(Shell)而已。客观上讲,壳是可以被替换的(即Exporer.exe程序)。
3. 核心包含了很多内容,简单而言,是:HAL模块、执行体模块、以及Win32子系统等。
Q:zr120633367
电脑打开其他文件夹很正常, 但打开指定的文件时却反应半天就是假死的样子。这是怎么回事呢?系统也重庆做过。
A:张佩
从你描述的现象很难给出答案,但我可以讲一讲。用户在文件管理器中打开文件夹,在干净的OS中,这个操作仅仅导致一系列的Open、Close、 QueryInformation等函数的调用,目地是请求系统返回文件夹中的所有文件的列表以及文件信息,从而桌面可以显示它们,这些操作一般不会耗费很多时间。
至于为什么非常慢,以至于假死,我怀疑你安装了某些软件,这些软件Hook了一些系统调用,会在你打开一个文件
或文件夹的时候,同时也对被打开的文件进行检查操作。比如杀毒、木马软件,或者像SVN、CVS等软件,都会这样做。
如果你安装了这些软件,可以先把它们挺掉。如果怀疑中毒的话,用 IceSword软件看看,它会检测Hook情况。再教你做这样一个实验:去网上下载名为FileMon的工具,它能够监测到所有的文件查询、读写操作,你在Options菜单中设置Filter为你的文件夹路径(比如C:\folder1),这样FileMon只会检测指定文件夹。然后你打开这个文件夹,FileMon会把所有操作记录下来。你会发现有很多Log的工作进程是桌面进程(Explorer.exe),这是正常的。然后就要看看,是否有其它进程也在同时操作这个文件夹,FileMon会记录操作发生时的时间,你可以据此做一些判断。
Q:chilewang
张工 你好!
我想咨询一下有关Windows下设备驱动开发的问题,目前我遇到一个问题是,如果设备断电自己关机的话,如何避免上位机Windows系统的蓝屏!
当我遇到这个问题时,我一直想象为什么DV机等这些USB设备在连接到电脑时,当关掉DV的电源时,电脑就不蓝屏。而我的也是USB连接设备,可设备一失去电源,与其连接的电脑就要蓝屏!如有描述不清,欢迎继续与我联系! 祝好~
A:张佩
很简单,调试你的IRP_MJ_PNP/IRP_MN_SURPRISE_REMOVAL和IRP_MJ_POWER/ IRP_MN_SET_POWER这两个分发函数。当设备突然移除的时候,会导致PNP和Set Power分发函数的调用。很显然,你的驱动没有处理好这些问题。
Q:dplm
张老师:你好。
请教一下U盘量产失败,或有时不明原因,U盘出现0字节,非物理损坏。是使用的软件有问题(或不持这个U盘),还是其它原因。理论上所有U盘都可以量产吗?
用其它工具制作U盘启动,如UltraISO,与量产技术之间有什么区别,实现的原理能简单介绍一下吗?
A:张佩
没认真研究过,Sorry,所以我不知道我下面的理解是否正确:
量产工具应该是更新USB的ROM,或者刷固件,所以有些假U盘、移动硬盘,显示出来是Apple公司生产的,淘宝上很多,拆开来看污七八糟。
UltraISO是改MBR扇区。本质上USB设备是没有扇区概念的,但它可以假定自己有,这样就可以实现U盘分区。
Q:sdbaby
你好张老师,我现在对于WINDOWS系统内核驱动,有一个想知道很久的问题!就是为什么WINDOWS98的时候(基于DOS下的系统)和 windows xp下的驱动 (基于NT系统) 前者有许多的驱动要自己安装 ,但是XP系统就可以自动安装上了!!!还有,上面的问题我们可以这样想,是基于DOS和NT系统的区别,但是WINDOWS 2000应该也是基于NT系统下的吧?为什么有的驱动也要自行安装呢???
张佩
如果有些驱动Win XP下不用手动安装,而2K下需要手动安装,这是由于2K系统没有带这些系统驱动,比如USB摄像头(即UVC驱动usbvideo.sys)和所有 1394相关的驱动程序,就是例子。这些由系统自带的驱动程序,或者某类默认设备驱动程序,我们称之为In-Box驱动。对于负责驱动检索、安装的PNP管理器,2k和XP是没有本质区别的。
Q:拿贝马凡
hello,张工,我想咨询下,nt内核中,钩子(hook)的作用,另外内核钩子与应用层钩子有什么区别?另外他们与ssdt的关系,谢谢
A:张佩
实现Hook的技术很多,分析如下:
1. 系统钩子,这是通过调用SetWindowsHook实现的。系统为某些消息专门准备了一个处理函数列表,调用这个函数,只是在列表中增加一项而已。
2. API钩子。这种钩子可以实现在用户/内核层。原理不复杂,就是想办法在让Hook的函数调用你的函数,或者压根用你的函数替代被Hook的函数。实现技术也分两种:
一种:很多函数地址是以指针形成保存在内存里面的,比如IRP分发函数,或者你提到的SSDT表中的系统服务,以及IDT表中的ISR,可以找到保存函数支持的地址,然后用新地址替代它们;
第二:在实现好的函数中,插入jmp或者call指令,调用或跳转到你的函数处执行,微软自己就有一个名为动态更改的库。
Q:wpp769
你好,我想请问下,我的笔记本系统刚装好,在设备管理器里面网卡驱动有2个,但过几天就变成5个了,而且3个都是带感叹号的,也就是说不可用。下载的网卡驱动也装不上。我只能重做系统。请问这样该怎么办?能不能不做系统就解决呢?谢谢
A:张佩
笔记本有两个网络设备是正常的,一个是以太网,一个无线网;如果有五个,那么一定是你安装了虚拟网卡,或者在安装诸如虚拟机、VPN等软件的时候,附带安装了这些虚拟网卡组件。你应当查看网络设备名称,并去网上搜索,会得到更多有用信息。
Q:Treasurecool
请问一下如何针对硬件进行驱动的开发,原理是什么啊,我是一个初学者,求解~~~
A:张佩
我不知道该怎么回答这个问题,我试着回答。
系统内核拥有和硬件通信的手段,即能够读写设备寄存器、读写设备内存。通过这些硬件通信手段,系统能够获取设备信息,或对设备进行相关配置,以完成设备接入系统后的初始化操作。然后可进一步进行IO通信,这主要通过读写设备内存完成。
这些和硬件之间的操作极为底层,如果把这些操作都交给第三方来做,不容易。所以操作系统会完成大部分底层操作,而留出接口给上层的内核模块调用。这些上层模块,即内核驱动。一般驱动会有多个或多层,层层封装,以让由用户自定义的驱动模块尽量简单。差不多这样。
------------------------------------------
下期(200期)门诊:Boost程序库的应用探讨
① 预告: Boost被称为“C++准标准库”,含有许多高质量的工具,如正则表达式、字符串算法、智能指针、散列容器等,弥补了C++98标准库的不足,可以构建 出工业级强度的构件,代表了目前C++所能达到的最高技术高度。但Boost程序库内容博大精深,又使用了大量的高级编程技巧,结构精致复杂,令不少程序 员望而生畏。
② 链接:http://doctor.51cto.com/develop-214.html