在OSX上创建实时线程

时间:2014-04-29 23:23:00

标签: multithreading macos real-time thread-priority mach

我正在开发一个OSX应用程序,它通过USB串口将数据传输到硬件设备。硬件有一个小的串行缓冲区,以可变速率耗尽,应始终保持非空。

我们在自己的NSThread中有一个写循环,它检查硬件缓冲区是否已满,如果没有,则写入数据直到它为止。大多数循环迭代不会写任何东西,几乎没有时间,但它们偶尔可能需要几毫秒(与CACurrentMediaTime同时)。线程在每次迭代后休眠100ns。 (我知道睡眠时间看起来非常短暂,但是如果我们把它搞砸了,硬件开始变得数据匮乏。)

这很有效。但是,如果主线程或其他应用程序开始执行处理器密集型操作,则写入线程会变慢并且无法足够快地传输数据以防止设备的队列清空。

所以,我们想要实时编写串行写入线程。我通过Mach API请求实时调度the Apple docs,然后尝试调整Chromium source中SetPriorityRealtimeAudio(mach_port_t mach_thread_id)的代码片段。

然而,这不起作用 - 应用程序仍然容易受到串行通信速度的影响。有任何想法吗?我不确定是否需要更改写线程的行为,或者我是否传递了错误的线程策略参数,或者两者都有。我尝试了各种周期/计算/约束值,并强制实现更加一致的占空比(写入最大100ns然后再睡100ns)但没有运气。

一个相关的问题:我如何直接检查线程的优先级,和/或告诉它是否是实时开始然后被降级而不是被提升开始?现在我只是从硬件性能上做出推断,因此很难确切知道发生了什么。

1 个答案:

答案 0 :(得分:0)

我的建议是将需要最高优先级的执行线程移动到一个单独的进程中。 Apple经常为实时流程执行此操作,例如驱动内置摄像头。根据您所定位的操作系统版本,您可以使用分布式对象(XPC的前身)或XPC。

您还可以滚动自己的RPC机制并使用标准的Unix fork技术来创建单独的子进程。由于您的主应用程序是子进程的所有者,因此除了进程中的各个线程优先级之外,您还应该能够设置进程的调度优先级。

当我编辑这篇文章时,我在后台播放了WWDC视频,并启动了QuickTime电影录制任务。如您所见,这两个应用程序的实时方面都在不同的XPC进程中运行:

ps -ax | grep Video
 1933 ??         0:00.08 /System/Library/Frameworks/VideoToolbox.framework/Versions/A/XPCServices/VTDecoderXPCService.xpc/Contents/MacOS/VTDecoderXPCService
 2332 ??         0:08.94 /System/Library/Frameworks/VideoToolbox.framework/Versions/A/XPCServices/VTDecoderXPCService.xpc/Contents/MacOS/VTDecoderXPCService

XPC Services at developer.apple.com

Distributed Objects at developer.apple.com