3

我正在为 MacOSX(Windows 已经运行)开发一个虚拟 USB 总线驱动程序,该驱动程序通过网络与一个 linux 盒连接。它在 10.6 和 10.7 下使用大容量存储设备和 HID 设备(如鼠标或键盘)运行良好。

但是对于 10.7(.5) 以下的 HID 设备,移除设备(拔出)或更简单的卸载 kext 失败,因为还有一个实例(分离后保留计数不会降为零)。我的 10.6 和 10.7 测试环境是相同的 MacBooksPro 8.2 i7。

有时(5-50 分钟)后,kext 会在我没有任何动作的情况下自由。它似乎不依赖于不断变化的电源模式。

是的,我有 USBFamily 日志库和大量输出,但是在工作(kextunload ok)和不工作运行之间,我发现日志没有区别,即使日志级别为 7。

由于大容量存储设备似乎运行良好,我猜问题出在 HID 驱动程序堆栈内部,尤其是在 10.7 下?

删除 10.6 和 10.7 之间的 USB HID 设备驱动程序堆栈是否有任何已知差异?

我的 kext 是一个(虚拟)ControllerV3 派生类,为任何真正插入的(在远程 linux 盒子上)USB 设备建立/创建一个 USBDevice。使用 XCode 4.4.1。

提前感谢您的任何想法或提示,关于马库斯

PS:在我看来有点奇怪,在 10.7 下有这么多 HID 对象位于驱动程序堆栈的顶部。在 kextunload 之后(失败“..VirDevice 有 1 个实例”),它们似乎还活着。但这 100% 与本地插入和拔出的罗技鼠标相同。

在我看来,只有最低的两个对象 MsVirBus (虚拟 USB 总线,派生自 IOUSBControllerV3 )和 Mouse@xaffe003f 是一个 IOUSBDevice 派生对象。

kextunload 后的驱动程序堆栈

4

1 回答 1

2

我对 HID 堆栈没有深入的经验,但我可以给你一些通用的 IOKit/kext 建议,告诉你如何追踪这类问题的根源。

kextunload调用terminate()I/O 注册表中的所有对象。这意味着有两种情况可能导致您最终无法卸载 kext:

  1. terminate()删除所有子对象失败或失败

  2. 剩余的活动对象都不在 I/O 注册表中

使用命令检查ioreg您的任何对象是否保留在 I/O 注册表中。还要检查他们有哪些客户,因为这些客户通常会阻止删除。

如果注册表中没有您的对象,则您很可能遇到了保留/释放不匹配的问题。我在这个答案中给出了一些关于追踪这些的建议,所以我不会在这里重复。这似乎也不太可能,因为您的 kext 最终会卸载并在 10.6 上运行。

如果您在 I/O 注册表中留下了对象,您将需要追踪为什么这些对象仍然存在。如果您尚未terminate()在类中覆盖,请添加虚拟覆盖,将调用转发到基类实现。但是用日志输出包装该转发调用,并输出调用是否成功。如果您已经覆盖terminate,请添加类似的日志记录。您可能还想为 添加类似的日志记录didTerminate(),因为终止可以是异步的。

拔下 USB 设备时,您应该将terminate()设备树向下传递给您的客户端。我会检查 EHCI 控制器代码的等效部分,看看是否需要任何特殊参数等。

于 2012-12-06T12:21:00.997 回答