我正在基于示例开发 coreaudio 用户空间 hal 插件 developer.apple.com/library/mac/samplecode/AudioDriverExamples/Introduction/Intro.html
在插件实现中,我计划从另一个进程即CFMessagePort获取音频数据
但是,我在尝试创建端口 CFMessagePortCreateLocal 时在控制台中收到以下错误...
sandboxd[251]: ([2597]) coreaudiod(2597) 拒绝 mach 注册 com.mycompnay.audio
我做了一些谷歌搜索并找到了这篇文章
技术问答QA1811 https://developer.apple.com/library/mac/qa/qa1811/_index.html 关于在plist中添加AudioServerPlugIn_MachServices但仍然没有成功。
我还需要做些什么才能使这项工作正常进行(例如添加权利、代码签名),或者这不是正确的方法。? 我不确定 MesssagePort 机制在沙箱下是否还能工作。 XPC 服务可行吗?
非常感谢您抽出宝贵的时间。非常感谢任何帮助
<小时/>更新1:
我应该在音频插件中创建一个远程端口而不是本地端口。话虽如此,使用 plist 中的 AudioServerPlugIn_MachServices 属性。现在控制台中没有 sandboxd[559]: ([552]) coreaudiod(552) Deny mach-lookup/register 消息。
但是,在我的音频 hal 插件(客户端)中,我有
CFStringRef port_name = CFSTR("com.mycompany.audio.XPCService");
CFMessagePortRef 端口 = CFMessagePortCreateRemote(kCFAllocatorDefault, port_name);
端口返回值 0。我在另一个应用程序中尝试过,效果很好。
这是我的服务器端:
CFStringRef port_name = CFSTR("com.mycompany.audio.XPCService");
CFMessagePortRef port = CFMessagePortCreateLocal(kCFAllocatorDefault, port_name, &callback, NULL, NULL);
CFRunLoopSourceRef runLoopSource =
CFMessagePortCreateRunLoopSource(nil, port, 0);
CFRunLoopAddSource(CFRunLoopGetCurrent(),
runLoopSource,
kCFRunLoopCommonModes);
CFRunLoopRun();
我确实收到了一条与此相关的控制台消息。
com.apple.audio.DriverHelper[1314]:名为 SimpleAudioPlugIn.driver 的插件需要扩展名为 com.mycompnay.audio.XPCService 的 mach 服务的沙箱
有人知道为什么吗?
<小时/>更新2
我注意到,当我使用 coreaudiod 的 Debug模式时,它确实成功获取了 mach 服务的对象引用。 (当我尝试 xpc_service 方法时也发生了同样的事情) project scheme setting
有人吗?
最佳答案
我很确定我的 AudioServerPlugIn 中遇到了同样的问题。我可以查找并使用我尝试过的每一个 Mach 服务,除了我创建的服务。我创建的那些可以按照常规流程正常运行。
最终我读到了the Daemonomicon并发现 coreaudiod (托管 HAL 插件)正在使用全局引导命名空间,但我的服务正在每用户引导命名空间中注册。由于“使用全局命名空间的进程只能看到全局命名空间中的服务”,我的插件无法看到我的服务。
您可以使用 launchctl
来测试这一点,方法是让它运行注册您的服务的程序,但使用与 coreaudiod
相同的引导命名空间。您可能需要禁用 rootless。
# launchctl bsexec $(pgrep coreaudiod) your_service_executable
运行后,尝试再次从您的插件连接。
从 Daemonomicon 的表 2 中,您可以看到只有 launchd 守护进程使用全局引导命名空间。这解释了为什么 coreaudiod 使用它。我认为这意味着您的 Mach 服务需要由 launchd 守护进程创建。
要制作一个,请创建一个 launchd.plist在 /Library/LaunchDaemons
中为您提供服务。将其所有者设置为 root:wheel
并使其只能由所有者写入。在其中设置 MachServices
键并添加您的服务名称:
<key>MachServices</key>
<dict>
<key>com.mycompany.audio.XPCService</key>
<true/>
</dict>
然后注册它:
# launchctl bootstrap system /Library/LaunchDaemons/com.mycompany.audio.XPCService.plist
这就是我最终得到的结果:com.bearisdriving.BGM.XPCHelper.plist.template 。请注意,如果没有 UserName
/GroupName
键,您的守护进程将以 root 身份运行。 (my service 和 plugin 的代码也位于该存储库中,以防有帮助。)
不幸的是,我最终不得不使用 XPC,但我首先尝试了 CFMessagePort,效果很好。
无论插件是否签名,似乎都工作正常。不过,正如您所说,您确实需要 Info.plist 中的 AudioServerPlugIn_MachServices
键。
关于plugins - 核心音频用户空间插件驱动程序 - 沙箱防止与另一个进程的数据交互,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33138275/