stoneyr
驱动牛犊
驱动牛犊
  • 注册日期2002-01-13
  • 最后登录2007-10-31
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:6049回复:27

关于WDM驱动程序的一些问题,想了很久都没有想通,特来此问

楼主#
更多 发布于:2004-10-15 20:03
1、系统检测到硬件时调用AddDevice例程让驱动程序增加一个硬件设备,但是如果创建的驱动程序并不针

对任何一个硬件,那这个AddDevice例程是什么时候被调用的呢?系统为什么要调用这个例程呢?比如一

个只有DriverEntry和AddDevice两个函数的驱动程序,同样也可以正常编译,正常安装,安装好后却发现

系统也正常调用了AddDevice例程。
2、WDM驱动程序在AddDevice里创建了一个设备,并注册了设备接口,其目的是为了给上层应用程序提供

访问该设备的接口。那就说在上层应用程序使用这个设备之前,这个驱动程序早就已经被装载,并且系统

已经调用了其AddDevice例程,要不然的话上层应用程序就没有设备接口可用了。那这个驱动程序是在什

么时候被装载的?在操作系统启动的时候?还是......?在INF文件里有一个控制驱动装载的选项,有一

个值是在系统需要的时候装载该驱动,但是什么时候才是系统需要的时候呢?
3、驱动程序里的各个例程,是运行在与上层应用相同的线程上下文环境,还是操作系统内核另外开一个

线程来执行该例程?如果是前者,那么驱动程序是如果实现对IRP的延迟处理的,因为如果延迟了,那上

层应用中线程不是也被阻塞了吗?如果是后者,操作系统对每一个活动的例程都要开一个线程,那不是要

占用系统很多的资源,这样为什么不会影响系统的性能?
4、驱动程序的代码在整个系统中是不是只有一份?也就是说如果驱动程序里有一个全局变量,那么访问

该全局变量的所有例程都就应该同步或互斥,而不象dll(Win2K)中的全局变量,即使是全局变量如果不

声明在共享数据段内都不是共享的。

最新喜欢:

xie_jian_junxie_ji... netelifeneteli...
stoneyr
驱动牛犊
驱动牛犊
  • 注册日期2002-01-13
  • 最后登录2007-10-31
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2004-10-16 11:18
怎么没有人关注?
神呀,帮帮我吧。
stoneyr
驱动牛犊
驱动牛犊
  • 注册日期2002-01-13
  • 最后登录2007-10-31
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2004-10-17 10:09
1.2:我的理解是:驱动程序在启动时(注册表中services中的start决定操作系统何时启动驱动程序,也可以在用户程序调用setup*函数启动驱动程序),支持完全PNP的驱动会由PNP管理器自动调用位于DeviceObject->DeviceExtension->AddDevice函数。对于非完全PNP驱动,AddDevice的功能在DriverEntry中实现。所以可以看到在很多NT驱动程序中并没有AddDevice函数。
3:我想是前者,但这个问题弄的不是很透彻,哪位出来说说?
4:一般是这样的,通常驱动所用的全局变量放在DevcieExtension中,而且必须同步操作。


如果如你所说,PNP管理器在调用AddDevice时,其参数中的PDO应该是指向什么设备对象呢?
如果全局变量放在DeviceExtension里,对于同一个驱动程序管理下的不同的设备,会有不同的值。如果需要它们具有相同的值的话,那是不是应该放在外面呢?对于声明为static的变量是不是对不同的设备具有相同的值呢?
stoneyr
驱动牛犊
驱动牛犊
  • 注册日期2002-01-13
  • 最后登录2007-10-31
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于:2004-10-18 19:55
建议搂主仔细的看看ddk的toaster例子(包括function driver和bus driver)
如果你把这个例子搞懂了,就不会再问上边的问题了。
 


好,仔细看看。
stoneyr
驱动牛犊
驱动牛犊
  • 注册日期2002-01-13
  • 最后登录2007-10-31
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2004-10-23 21:06
怎么理解“随机的进程”?
随机是不是就是说无进程?还是怎么回事?Windows不会随便中止一个进程然后就执行驱动程序,那一个系统这么驱动程序,任意一个随时都可能会终止了?
stoneyr
驱动牛犊
驱动牛犊
  • 注册日期2002-01-13
  • 最后登录2007-10-31
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2004-10-23 22:12
还有一个问题:
总线驱动程序,是不是既作为该总线的功能驱动程序,又作为其所创建的每一个PDO的功能驱动程序?
也就是在系统加载总线驱动程序时,PNP管理器调用该总线驱动程序的AddDevice例程,这时它创建一个对应的FDO,总线驱动程序得以枚举接在其上的设备,当枚举到一个物理设备时,创建对应的PDO,并通知PNP管理器加载相应的功能驱动,这个功能驱动程序不管它下面的PDO,而是由总线驱动程序接管。
是不是这样?
stoneyr
驱动牛犊
驱动牛犊
  • 注册日期2002-01-13
  • 最后登录2007-10-31
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2004-10-28 16:34
关于楼主的问题,偶的看法:(不保证正确哈 :cool:)

1:AddDevice通常是系统在发现新设备的时候,根据注册表中各设备与驱动的关联调用的。可以参考一下设备堆栈的形成过程。 象你说的那种没有任何原因,AddDevice就被调用的情况我还没发现。(不排除没有跟踪到哈~) 你是否可以举个例子? (注意你的设备类型和安装选项。比如说:UpFilter。。。)

2:我想Driver的载入顺序和安装时的启动选项有关吧?

3:和被调用的方式有关。 driver本身可以看做是内存中的一个模块,提供了一些接口。那个线程来调用它,它就处于那个线程的上下文。(这好像是句废话 :D) 系统调用的方式可以有很多种,看你driver的层次。有一种情况是可以肯定的,当你用DeviceIoControl与driver通信的时候,driver处于你的AP所处的上下文。(其实你可以做一些试验 :))

4:偶也不太清楚。 driver里的全局变量应该是唯一的。(互斥应该是须要的) dll(2k)里的某些数据段采用的是copy on write的机制。

这些东东偶也考虑过很久,很多没搞清楚。  


一个简单的例子就是如果你写一个驱动程序只有DriverEntry和AddDevice两个例程,正常安装后你就知道当安装好后,AddDevice已经被调用了。明显没有相应的硬件。
什么线程调用这些例程,则这些例程在该线程的上下文中运行,这个我可以理解,开始的时候我也是这样理解的,但是有一点我不是很明白,就是当你调用IoCallDriver时,如果返回IO_PENDING,那么这个IRP跑哪去了?传递下去后的处理会在哪个线程呢?因为前一个线程已经被调用IoCallDriver的函数终止并返回了。
现在我想大概是这样的,如果出现这种情况,操作系统会给这个IRP新开一个线程,到合适的时候会调入该线程来处理该IRP,因为那天我在书上看到IRP结构中有一个很重要的不可访问的域threadentries(好象是这么写的)。
stoneyr
驱动牛犊
驱动牛犊
  • 注册日期2002-01-13
  • 最后登录2007-10-31
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2005-03-22 18:46
1.PnP管理器为每个设备实例调用AddDevice routine,如果有设备的,首先要在inf文件里面指定加载的设备,如果一个设备也没有的话,嘿嘿,就像filter driver,你总要加到某个driver上去吧,所以AddDevice总会被调用的,才能生成设备栈,这样才符合WDM的构架。
2.何时load driver,由inf文件的start type来决定,如3,就是booting windows时候加载driver,如果为1,就是由自己的用户程序使用到driver的时候,来加载它,当然要有管理员的权限,通过CreateService,StartSerive来实现动态安装driver,其实就是交给system.exe来实现。
3.内核模式的例程运行在下面三种不同的上下文之一:
- 系统进程上下文
- 特定用户线程(和进程)上下文
- 任意用户线程(和进程)上下文
一个驱动程序的DriverEntry(…)函数总是运行在系统进程的上下文中,系统进程上下文和用户上下文无关(因此没有TEB)。DPCs(例如一个驱动程序为ISR服务的DPC或者定时器到期函数)运行在任意用户线程的上下文中。这意味者在一个DPC的执行过程中,任何用户线程都可以成为“当前”线程,因此任何用户进程都可以映射到内核虚拟地址空间的低2GB中。当一个设备直接被用户访问而不涉及其他驱动程序时,该设备的驱动程序的分派线程总是运行在发出请求的用户线程中。
4.DriverEntry只会被调用一次,AddDevice可以被多个设备调用,so,DeviceExterntion对应每一个设备。全局变量只有一个,so,必须作互斥访问。

以上只是个人理解,可能有不对的地方,还请高人指教。


好,要的就是你这样的回答。
但是对于第二个问题,可能是我没有表达清楚,还有一个重点的小问题在里面:由于是在AddDevice里调用IoRegisterDeviceInterface的,而AddDevice是在DriverEntry以后才会被调用,而这个DeviceInterface是提供给就用程序的,就用程序只有找到该DeviceInterface后才能启动驱动程序(我们暂时不说在系统启动时加载的那种类型),这样才能调用DriverEntry,再调用AddDevice,再调用IoRegisterDeviceInterface,那这个不就是一个鸡生蛋,蛋生鸡的问题了吗?
stoneyr
驱动牛犊
驱动牛犊
  • 注册日期2002-01-13
  • 最后登录2007-10-31
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2005-03-23 13:15
关键是一个先与后的问题呀,
应用程序总得要有接口才能通知PNP管理器调用DriverEntry,
但是在AddDevice里接口才被注册,
而在DriverEntry里才能通知到PNP管理器AddDevice的地址,

这样的话,刚开始的时候,应用程序怎么知道接口在哪呢?
游客

返回顶部