magicfound
驱动牛犊
驱动牛犊
  • 注册日期2005-06-01
  • 最后登录2010-05-16
  • 粉丝0
  • 关注0
  • 积分5分
  • 威望8点
  • 贡献值0点
  • 好评度7点
  • 原创分0分
  • 专家分0分
阅读:2415回复:8

2k是按照ServiceGroupOrder+GroupOrderList的顺序先加载完驱动,再构建设备树;还是在构建设备树时需要相应的驱动,再加载驱动?

楼主#
更多 发布于:2005-06-01 10:35
谢谢大家解答我的疑惑。

最新喜欢:

LeopardLeopar...
magicfound
驱动牛犊
驱动牛犊
  • 注册日期2005-06-01
  • 最后登录2010-05-16
  • 粉丝0
  • 关注0
  • 积分5分
  • 威望8点
  • 贡献值0点
  • 好评度7点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2005-06-06 16:08
领悟中...
谢谢tiamo的解答,谢谢大家的解答。
tiamo
VIP专家组
VIP专家组
  • 注册日期2002-02-26
  • 最后登录2018-01-09
  • 粉丝17
  • 关注4
  • 积分50分
  • 威望142点
  • 贡献值1点
  • 好评度40点
  • 原创分2分
  • 专家分15分
  • 原创先锋奖
  • 社区居民
板凳#
发布于:2005-06-03 13:51
整个的过程是这样的

首先明确几个步骤概念

加载....表示把文件加载到内存

调用driverentry..如名

调用adddevice

发送IRP_MN_START_DEVICE,以及后续及前导的其他的PNP request

这几个步骤基本不是一次完成的(指系统启动的过程)

然后..希望你手头上有win2k的源代码...可以对比跟踪

首先是加载过程
被标记成boot start的驱动是由osloader.exe加载的.这个文件是作为一个组件(这样翻译?)被放置在ntldr里面了,可惜ms没有提供这个pdb文件下载.
这些boot start的driver跟hal.dll和ntoskrnl.exe一同被加载
如果你有设置noguiboot的话.能看到加载的顺序的.顺便你还能看到几个非驱动文件被加载比如drvmain.sdb

当内核ntoskrnl开始执行以后,经过漫长的过程来到IoInitSystem这个函数.然后调用IopInitializeBootDrivers这个函数

所谓boot driver就是指由osloader.exe加载的驱动
这个函数首先把诸多的boot drivers按照他们的group:tag顺序排序
然后一一调用IopInitializeBuiltinDriver这个函数.
注意这里的group:tag起的作用

在IopInitializeBuiltinDriver函数里面..调用这个driver的入口函数,也就是driverentry

函数IopInitializeBuiltinDriver完成,回到IopInitializeBootDrivers函数

接着调用IopAddDevicesToBootDriver这个函数.为刚刚创建的driver调用他的adddevice函数.然后返回

接着IopInitializeBootDrivers这个函数调用IopRequestDeviceAction从root开始枚举每个节点
为每个没有被处理的节点分配资源.然后start这个节点

start了以后再发送IRP_MN_QUERY_DEVICE_RELATIONS的bus relation去枚举子节点.并企图为这个子节点adddevice.并再企图start 这个子节点.并发送query bug relation到这个子节点,并递归的处理子节点的子节点.并一直递归...这个动作要特别注意

当系统在执行IopInitializeBootDrivers的时候是不能从磁盘上加载驱动的.所以在企图加载driver的时候除非这个driver object已经被创建了.才会成功.否则会失败.既便是当前这个driver的image已经位于内存里面了.

源代码里面使用的是driverObject = IopReferenceDriverObjectByName(&unicodeDriverName);这个语句来获取当前这个driver object是否已经存在..显然只有在driver entry被调用了以后他才会存在.(IopCallDriverAddDeviceQueryRoutine这个函数里面)

如果当前的driver object不存在,而且又不能加载驱动.那么这个递归的过程就结束了.一路返回到IopInitializeBootDrivers这个函数

这个函数继续按照group:tag的顺序走下一个驱动.调用driver entry调用adddevice 企图start device企图枚举他的孩子..
这里还要特别注意的时候.IopRequestDeviceAction这个函数始终是从root节点开始的.这样就存在这样的情况

比如
acpi.sys要先于pci.sys被调用driverentry
acpi的driverentry调用了以后,adddevice被接着调用,然后是start device.然后被query bus relation.他返回一个pdo是pci.sys的
内核企图为新返回的pci.sys的pdo adddevice.当然失败了.因为pci.sys的driverentry并没有被调用.acpi的调用结束回到IopInitializeBootDrivers函数,他开始尝试下一个要被处理的boot driver,这里我们简单起见假设下一个就是pci.sys,可能实际上排在acpi.sys后面的并不一定就是pci.sys

接着pci.sys被调用driverentry,接着adddevice,然后是start,然后被query bus rel,假设pci返回了一个pdo是pciide.sys的.当然企图为pciide调用adddevice还是失败了.又回到了IopInitializeBootDrivers函数..开始尝试下一个group:tag组合

最终IopInitializeBootDrivers函数一一遍历了全部的boot driver
这个时候device tree上可能有很多的节点并没有被调用adddevice..因为在这个过程中是不能加载驱动的.

等全部的boot driver都被初始化好了.IoInitSystem调用IopInitializeSystemDrivers函数俩完成那些标记成system start的驱动加载过程

IopInitializeSystemDrivers函数首先处理当前device tree那些没有被adddevice的节点..从root节点开始调用IopProcessAddDevices但是这一次设置了loadDriver = TRUE,也就是说如果在上面的流程里面企图adddevice却发现driver object不存在的时候,就不再是简单的返回一个错误了.而是开始尝试加载image文件,调用driver entry
然后继续..这个步骤里..很多的设备驱动都被加载进来了.基本的pnp device tree在这个步骤里面基本成形.

完成了上面的工作以后
IopInitializeSystemDrivers安装group:tag的顺序收集所有被标记成system start的驱动.一一加载image文件,调用driverentry调用adddevice(如果有的话,因为system start多是一些软件驱动,一般都没有adddevice)
这些都完成了以后..基本驱动加载就完毕了

最后剩一个auto start的类型..那是由scm加载的.

整个过程是比较复杂的
希望手头准备好win2k的源代码.然后使用windbg一点点跟踪调试.
大致就能明白整个过程了.这里特别推荐windbg.softice会错过很多东西...呵呵...windbg能在ntoskrnl.exe执行之前就断点.而且windbg调试的时候你也能很方便的对比win2k的源代码.

以上
magicfound
驱动牛犊
驱动牛犊
  • 注册日期2005-06-01
  • 最后登录2010-05-16
  • 粉丝0
  • 关注0
  • 积分5分
  • 威望8点
  • 贡献值0点
  • 好评度7点
  • 原创分0分
  • 专家分0分
地板#
发布于:2005-06-02 16:10
猜测是这样:pnpmanager先玫举设备树,当某一类设备被玫举完,设备树的构建暂停,pnpmanager就玫举它的下一类legacy设备,然后再继续构建设备树。为什么要插入legacy设备的玫举呢?是因为后来玫举的设备可能要被上面的legacy设备管理。比如 NDIS.SYS 的加载就在 网卡驱动 的前面,因为 网卡 要被 NDIS 管理。

是这样的吗?
magicfound
驱动牛犊
驱动牛犊
  • 注册日期2005-06-01
  • 最后登录2010-05-16
  • 粉丝0
  • 关注0
  • 积分5分
  • 威望8点
  • 贡献值0点
  • 好评度7点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2005-06-02 15:51
仔细读了你的文章《device tree的搭建过程》,设备树的构建过程基本弄清楚了,但我的主要问题在驱动的加载过程。用icesword看到的驱动加载顺序和想象并不一样。legacy driver当然也在设备树中,实际上是挂在pnpmanager下,包括pnp设备的根ACPI_HAL也都挂在pnpmanager下。按照想象pnpmanager应先玫举pnp设备构建设备树,并按相应的顺序加载驱动;然后玫举legacy driver,并按相应的顺序加载驱动,但加载驱动的顺序并不是这样。这是为什么呢?
tiamo
VIP专家组
VIP专家组
  • 注册日期2002-02-26
  • 最后登录2018-01-09
  • 粉丝17
  • 关注4
  • 积分50分
  • 威望142点
  • 贡献值1点
  • 好评度40点
  • 原创分2分
  • 专家分15分
  • 原创先锋奖
  • 社区居民
5楼#
发布于:2005-06-02 09:42
都不是....

说起来很复杂

用我的用户名搜索
我有写一个device tree的构建过程

既便是legacy driver比如file system这些
他也是位于device tree里面的

你可以试着向系统的root device发送一个query bus relationship的irp瞧瞧他都返回了些什么东西.....
会发现ndis,file system这些东西都历历在目

以上
zhangshengyu
驱动老牛
驱动老牛
  • 注册日期2003-10-03
  • 最后登录2016-07-26
  • 粉丝0
  • 关注0
  • 积分792分
  • 威望696点
  • 贡献值41点
  • 好评度499点
  • 原创分0分
  • 专家分0分
  • 社区居民
6楼#
发布于:2005-06-02 09:36
谢谢大家解答我的疑惑。

对于标准的设备驱动(如磁盘,打印机等)程序,这个是没用的。
---内核开发合作或提供基础技术服务QQ:22863668 ---
magicfound
驱动牛犊
驱动牛犊
  • 注册日期2005-06-01
  • 最后登录2010-05-16
  • 粉丝0
  • 关注0
  • 积分5分
  • 威望8点
  • 贡献值0点
  • 好评度7点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2005-06-01 17:39
但是我用icesword看到的加载顺序是,在加载pci.sys后,并没有继续构建设备树,而是加载了一些遗留的驱动,就好像是构建设备树和加载遗留驱动交叉进行,但总体还是依照sevicegruoporder+grouporderlist的顺序加载。是这样的吗?
zhaock
驱动太牛
驱动太牛
  • 注册日期2002-01-26
  • 最后登录2018-06-02
  • 粉丝3
  • 关注2
  • 积分73328分
  • 威望362317点
  • 贡献值1点
  • 好评度226点
  • 原创分0分
  • 专家分0分
  • 社区居民
8楼#
发布于:2005-06-01 13:22
这个要具体问题具体分析,对于wdm硬件驱动,显然是构建设备树的时候加载相应的驱动。对于象文件系统,ndis,tdi这种nt架构的驱动,就要按照sevicegruoporder+grouporderlist来加载了,也不存在象wdm那种设备树。windows内核的程序,都统称为驱动程序,但
但象文件系统,协议栈的程序,和那种一般意义上的驱动,差的很远了,当然在nt系列的平台上都要符合irp这种架构
游客

返回顶部