Macos Can';t卸载内核扩展;类有实例

Macos Can';t卸载内核扩展;类有实例,macos,kernel-module,kernel,kernel-extension,Macos,Kernel Module,Kernel,Kernel Extension,我正在为音频设备驱动程序(它是软件,但模拟硬件设备)编写OSX内核扩展 在开发过程中,完全卸载现有的旧版本,然后从头开始构建和安装新版本会很方便。但是,如果不重新启动系统,这有时似乎是不可能的 程序本身未运行,源文件已从/System/Library/Extensions/目录中删除 但是kextstat显示了一个实例: $ kextstat | grep 'com.foo.driver.bar' 219 0 0xfff123 0x5000 0x5000 com.foo.driver.bar (

我正在为音频设备驱动程序(它是软件,但模拟硬件设备)编写OSX内核扩展

在开发过程中,完全卸载现有的旧版本,然后从头开始构建和安装新版本会很方便。但是,如果不重新启动系统,这有时似乎是不可能的

程序本身未运行,源文件已从
/System/Library/Extensions/
目录中删除

但是
kextstat
显示了一个实例:

$ kextstat | grep 'com.foo.driver.bar'
219 0 0xfff123 0x5000 0x5000 com.foo.driver.bar (0.0.1) <102 5 4 3>
发生这种情况时,无法“强制”卸载kext(据我所知)


由于运行操作系统内核在内存中保存了一个引用,所以我猜这个实例仍然存在,对吗?这似乎不对,因为那样的话,
kextunload
总是会失败。那么为什么
kextnload
有时只需要重新启动系统来“完全”卸载所有驱动程序实例呢?

为IOKit kext运行
kextnload
会(如果没有其他kext依赖它)导致内核尝试
终止()该kext中I/O Kit注册表中的任何类实例。然后,它将等待一段时间,检查kext的类是否还有实例。如果没有,它将卸载kext。如果实例仍然存在,
kextunload
将失败(但是,终止的实例仍然处于终止状态;这意味着不会在其提供程序上重新运行I/O工具包匹配)

所以不管怎么说,你还是会得到一些真实的例子

  • 一种可能是您的对象拒绝
    终止()
    。如果客户机不放弃控制,则可能发生这种情况,例如,您无法卸载顶部安装了文件系统的磁盘的驱动程序。不响应终止消息的用户空间客户端是另一个例子

  • 否则,实例将终止,但不会被释放。由于它们似乎属于您的两个主要驱动程序类,如果您没有任何用户客户端不会放弃其声明,我将冒险建议您使用循环引用。如果不是这样的话,您只需查找
    retain()
    s,而
    release()
    则不匹配。我给出了一些关于如何追踪这些信息的提示

如果实例终止并取消注册,它们将不再出现在
ioreg
命令行工具的输出中,因此这是检查这两种情况中哪一种适用于此处的简单方法

Index Refs Address Size Wired Name (Version) <Linked Against>
$ 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).