我正在研究一些用于IOConnectCallAsyncScalarMethod()
从 DriverKit 扩展中获取回调的代码。设置非常繁重,包括生成线程、手动创建 a CFMachPortRef
、将其添加CFRunLoopSourceRef
到 aCFRunLoop
然后抽取该运行循环。
为了简化此代码并降低竞争条件的风险,我想在调度队列上获取 IOKit 回调。有什么办法可以做到这一点?
我正在研究一些用于IOConnectCallAsyncScalarMethod()
从 DriverKit 扩展中获取回调的代码。设置非常繁重,包括生成线程、手动创建 a CFMachPortRef
、将其添加CFRunLoopSourceRef
到 aCFRunLoop
然后抽取该运行循环。
为了简化此代码并降低竞争条件的风险,我想在调度队列上获取 IOKit 回调。有什么办法可以做到这一点?
在这件事上来回折腾,最终还是在OS X and iOS Kernel Programming一书(第 95 页,清单 5-15)中找到了答案。
诀窍是使用IONotificationPortRef
withIONotificationPortSetDispatchQueue
来设置目标调度队列。然后实际上将回调调度到该队列,设置io_async_ref64_t
并使用它。以下是代码的概要:
// Create a notification port for IOKit service callbacks
IONotificationPortRef notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
// Run notification callbacks on the desired dispatch queue
IONotificationPortSetDispatchQueue(self.notificationPort, dispatch_get_main_queue());
io_async_ref64_t asyncRef;
asyncRef[kIOAsyncCalloutFuncIndex] = (uint64_t)callback;
asyncRef[kIOAsyncCalloutRefconIndex] = (uint64_t)(__bridge void *)self;
uint32_t cmd = 0xCAFE; // Method as defined by the service
kern_return_t error = IOConnectCallAsyncScalarMethod(connection, cmd, IONotificationPortGetMachPort(notificationPort), asyncRef, kIOAsyncCalloutCount, NULL, 0, NULL, NULL);
callback
应该有这个签名:void commandReadyCallback(void *context, IOReturn result)
. (又名。IOAsyncCallback0
)
我希望这对将来的一些可怜的灵魂有所帮助。