IOKit 驱动程序已加载但未启动
IOKit driver is loaded but not started
我有 IOKit 基础驱动程序,它是非硬件触发的并且派生自 IOResources。它还使用 IOServiceOpen
向用户 space 客户端 class 提供,但我认为这与我的问题无关...主驱动程序具有派生驱动程序中提到的 IOKit 依赖性 Info.plist 文件:
<key>OSBundleLibraries</key>
<dict>
...
..
.
<key>com.derived.driver</key>
<string>1.0.0</string>
</dict>
另一个驱动程序(由 com.derived.driver
标识)作为通用内核扩展实现并存储在 /Library/Extensions
.
当我加载基本驱动程序时,派生驱动程序会自动加载。由于派生驱动程序驻留在 /Library/Extensions
中,因此也可以在 kextcache
.
触发派生驱动程序之前加载它
但是,当我将派生驱动程序从通用格式转换为 IOKit 格式时它停止工作,因此现在两个驱动程序 IOProviderClass
都是 IOResources
。
派生驱动程序似乎只是拒绝启动它基于 IOService 的 class,输出日志中没有任何错误迹象(我使用了调试器并看到它实际上达到了 IOService::probeCandidates
但不是 IOService::startCandidate
。由于内核是通过优化编译的,所以我无法确定确切的流程)。
当我通过 kextstat
查看当前加载的驱动程序时,似乎两个驱动程序都已加载,但根据 ioreg
只有基本驱动程序有活动实例(我期望两个驱动程序都会共享同一个提供者,即 IOResources)。
此外,一段时间后,似乎更高级的驱动程序简单地从加载的 kexts 中删除了(可能是由于闲置)..
我的设计是否合法,或者我是否还必须将基础驱动程序中的 IOProviderClass
字段从 IOResources
更改为基于派生驱动程序 IOService 的 class.
<key>IOKitPersonalities</key>
<dict>
<key>myDriver</key>
<dict>
<key>CFBundleIdentifier</key>
<string>com.base.driver</string>
<key>IOClass</key>
<string>com_base_driver</string>
<key>IOProviderClass</key>
<string>com_derived_driver</string>
编辑:
我确实做到了,而且有效(所有实例都已根据 ioreg 进行了初始化)。
+-o com_derived_driver <class com_derived_driver, id 0x10000091f, registered, matched, active, busy 0 (804415 ms), retain 6>
+-o com_base_driver <class com_base_mng, id 0x100000920, registered, matched, active, busy 0 (0 ms), retain 9>
但我真的不知道为什么,任何解释将不胜感激。
谢谢!
我只能猜测,因为您还没有提供完整的信息——特别是,您还没有提供您的两个驱动程序的完整 IOKit 个性词典。
请注意,通常只有一个服务会成功匹配一个IOService
成为它的客户端。如果您希望匹配多个不同类型的客户,他们需要通过个性字典中的IOMatchCategory
键定义不同的匹配类别。很多驱动需要专门匹配IOResources
,所以the rule for that case is to use the bundle identifier as match category。我怀疑这是你错过的?
最后,关于您在使用默认发行版内核时遇到问题的附注:内核调试工具包 (KDK) 提供备用 development 和 debug 内核,这些内核使用的优化设置要少得多。您可能会发现它们很有帮助 - 查看 KDK 的自述文件以了解有关如何启用它们的详细信息。
我有 IOKit 基础驱动程序,它是非硬件触发的并且派生自 IOResources。它还使用 IOServiceOpen
向用户 space 客户端 class 提供,但我认为这与我的问题无关...主驱动程序具有派生驱动程序中提到的 IOKit 依赖性 Info.plist 文件:
<key>OSBundleLibraries</key>
<dict>
...
..
.
<key>com.derived.driver</key>
<string>1.0.0</string>
</dict>
另一个驱动程序(由 com.derived.driver
标识)作为通用内核扩展实现并存储在 /Library/Extensions
.
当我加载基本驱动程序时,派生驱动程序会自动加载。由于派生驱动程序驻留在 /Library/Extensions
中,因此也可以在 kextcache
.
但是,当我将派生驱动程序从通用格式转换为 IOKit 格式时它停止工作,因此现在两个驱动程序 IOProviderClass
都是 IOResources
。
派生驱动程序似乎只是拒绝启动它基于 IOService 的 class,输出日志中没有任何错误迹象(我使用了调试器并看到它实际上达到了 IOService::probeCandidates
但不是 IOService::startCandidate
。由于内核是通过优化编译的,所以我无法确定确切的流程)。
当我通过 kextstat
查看当前加载的驱动程序时,似乎两个驱动程序都已加载,但根据 ioreg
只有基本驱动程序有活动实例(我期望两个驱动程序都会共享同一个提供者,即 IOResources)。
此外,一段时间后,似乎更高级的驱动程序简单地从加载的 kexts 中删除了(可能是由于闲置)..
我的设计是否合法,或者我是否还必须将基础驱动程序中的 IOProviderClass
字段从 IOResources
更改为基于派生驱动程序 IOService 的 class.
<key>IOKitPersonalities</key>
<dict>
<key>myDriver</key>
<dict>
<key>CFBundleIdentifier</key>
<string>com.base.driver</string>
<key>IOClass</key>
<string>com_base_driver</string>
<key>IOProviderClass</key>
<string>com_derived_driver</string>
编辑: 我确实做到了,而且有效(所有实例都已根据 ioreg 进行了初始化)。
+-o com_derived_driver <class com_derived_driver, id 0x10000091f, registered, matched, active, busy 0 (804415 ms), retain 6>
+-o com_base_driver <class com_base_mng, id 0x100000920, registered, matched, active, busy 0 (0 ms), retain 9>
但我真的不知道为什么,任何解释将不胜感激。
谢谢!
我只能猜测,因为您还没有提供完整的信息——特别是,您还没有提供您的两个驱动程序的完整 IOKit 个性词典。
请注意,通常只有一个服务会成功匹配一个IOService
成为它的客户端。如果您希望匹配多个不同类型的客户,他们需要通过个性字典中的IOMatchCategory
键定义不同的匹配类别。很多驱动需要专门匹配IOResources
,所以the rule for that case is to use the bundle identifier as match category。我怀疑这是你错过的?
最后,关于您在使用默认发行版内核时遇到问题的附注:内核调试工具包 (KDK) 提供备用 development 和 debug 内核,这些内核使用的优化设置要少得多。您可能会发现它们很有帮助 - 查看 KDK 的自述文件以了解有关如何启用它们的详细信息。