windows下 pnp设备的即插即用功能是怎么实现的?
看到 windows内核情景分析里说
加载驱动有三种方式 前两种是静态 分别是引导操作系统时和系统初始化时
最后一种是动态 使用NtLoadDriver
这种方法不会调用驱动的AddDevice函数
那pnp的即插即用又是怎么实现的?
pnp驱动和legacy驱动的本质区别是什么?
有无AddDevice? 堆叠的位置?有无PNP_MJ_XX 分发函数?
怎样才能让一个通过NtLoadDriver的legacy驱动 拥有 即插即用功能?
即插即用到底是怎么实现的?
[解决办法]
1、NtloadDriver只是负责调用DriverEntry,任何Driver都会有这个过程。
2、AddDevice是由Pnp模块来管理的,反过来。Pnp如果发现要装载的Driver不在系统中,也会调用类似NtLoaDriver的函数来装载。LoadDriver跟AddDevice就没有关系。
3、只要用AddDevice进来的,都是PNP管理模块处理的,必定是在设备枚举链中的,AddDevice传进来都是PDO,也就是硬件BUG的子DeviceObject,是通过向父设备发IRP_MN_QUERY_DEVICE_RELATIONS获得的DeviceOBJ。
4、如果你是FDO或Filter Driver,也算是legacy驱动程序,也可以自已先将其LoadDriver进来。然后,Pnp在后面,如果发现你的FDO或Filter Driver的PDO产生了,就会根据注册表中的驱动关系来一个一个AddDevice。
即插即用不是一种功能,而是一种方法,一种过程,一种系统识别Device的方法,不知道你说的这句话是沙意思:怎样才能让一个通过NtLoadDriver的legacy驱动 拥有 即插即用功能?
很多端口驱动程序都不走完整的PNP_MJ_XX,8042用的函数指针回调,比较少见的方法,甚至还有MiniPort 驱动程序没有PNP_MJ。
================补充一下:
不同类型的驱动程序装载方法完全不一样。
如果是PnP的,装载是通过驱动程序枚举关系来装载的。也就是说,大部份的硬件驱动程序,都是从ACPI_HAL(由ZwCreateDriver装载内存Driver)为根,然后找到一个子设备就根据这个子设备所安装驱动程序情况来装载,如果没有安装这个子设备的驱动程序,就不会装载,如果不需要安装的或已经安装的,就直接在查出这个设备的Driver,然后Load这个driver,然后AddDevice,过程大概如下:
开机:
1、PNPMGR 用IRP_MN_QUERY_DEVICE_RELATIONS问 ACPI_HAL,你有子设备没有?
2、ACPI_HAL回答,有一个,并返回这个DeviceObject(这个DeviceObject就通过自已驱动程序所用的方法去发现了设备,是ACPI_HAL自已在DriverEntry时建立的,PCI.sys是去查PCI总线,然后为每个设备建立一个DeviceOBJ),这个DeviceObj是普通的DeviceOBJ,
3、Pnp收到这个子设备后,将其标记为PDO(增加一些成员,如DeviceNODE)
4、Pnp去查这个子设备,获得硬件ID,兼容ID、设备路径等
5、PNP根据设备路径,找到这个设备在注册表中的安装情况(不需要安装的设备不在这里说了),ENUM下。
6、如果未安装(进Windows桌面后会说找到新硬件,问你要驱动程序),则返回到1的过程,做递归。
7、如果已经安装,则找出这个程序的FDO和PDO Filter Driver,然后依次LoadDriver(如果已经Load过,则跳过),同时依次AddDevice。
然后StartDevice.....
然后递归。
上面全是自已写的,有些述语可能不对。