我正在为音频设备驱动程序编写 OSX 内核扩展(它是软件,但模拟硬件设备)。
在开发过程中,完全卸载现有的旧版本,然后从头开始构建并安装新版本会很方便。但是,有时如果不重新启动系统,这似乎是不可能的。
程序本身没有运行,源文件已从/System/Library/Extensions/
dir.
But kextstat
显示单个实例:
$ kextstat | grep 'com.foo.driver.bar'
219 0 0xfff123 0x5000 0x5000 com.foo.driver.bar (0.0.1) <102 5 4 3>
(...意义:)
Index Refs Address Size Wired Name (Version) <Linked Against>
所以我的驱动程序实例有 0 个引用,但是kextunload
有时会失败,抱怨现有实例:
$ sudo kextunload -b com.foo.driver.bar
(kernel) Can't unload kext com.foo.driver.bar; classes have instances:
(kernel) Kext com.foo.driver.bar class FooBarDriver has 1 instance.
(kernel) Kext com.foo.driver.bar class com_foo_driver_bar has 1 instance.
Failed to unload com.foo.driver.bar - (libkern/kext) kext is in use or retained (cannot unload).
当发生这种情况时,没有办法“强制”卸载 kext(据我所知)。
我是否正确猜测这个单个实例仍然存在,因为正在运行的操作系统内核在内存中保存了引用?这似乎不对,因为那时kextunload
总是会失败。那么为什么kextunload
仅有时需要重新启动系统才能“完全”卸载所有驱动程序实例?
Running kextunload
对于 IOKit kext 将(如果没有其他 kext 依赖它)导致内核尝试terminate()
该 kext 中位于 I/O Kit 注册表中的类的任何实例。然后它会稍等一下并检查该 kext 的类中是否仍有实例。如果没有,它将卸载 kext。如果实例仍然存在,kextunload
失败(不过,终止的实例保持终止状态;我的意思是 I/O 套件匹配不会在其提供程序上重新运行)。
所以不知何故,你仍然会得到实时实例。
一种可能性是你的对象拒绝terminate()
。如果他们的客户不会放弃控制权,则可能会发生这种情况,例如您无法卸载顶部已安装文件系统的磁盘的驱动程序。不响应终止消息的用户空间客户端是另一个示例。
否则,实例将终止,但不会被释放。由于它们似乎属于您的两个主要驱动程序类别,因此如果您没有任何不会放弃其声明的用户客户端,我将冒险并建议您可能有一个循环引用。如果不是这样,你只需要寻找retain()
s 与 a 不匹配release()
。我给出了一些关于如何追踪这些的提示在这个答案中.
如果实例终止并取消注册,它们将不再出现在ioreg
命令行工具,因此这是检查此处适用两种情况中哪一种的简单方法。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)