2

我正在研究一些用于IOConnectCallAsyncScalarMethod()从 DriverKit 扩展中获取回调的代码。设置非常繁重,包括生成线程、手动创建 a CFMachPortRef、将其添加CFRunLoopSourceRef到 aCFRunLoop然后抽取该运行循环。

为了简化此代码并降低竞争条件的风险,我想在调度队列上获取 IOKit 回调。有什么办法可以做到这一点?

4

1 回答 1

2

在这件事上来回折腾,最终还是在OS X and iOS Kernel Programming一书(第 95 页,清单 5-15)中找到了答案。

诀窍是使用IONotificationPortRefwithIONotificationPortSetDispatchQueue来设置目标调度队列。然后实际上将回调调度到该队列,设置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

我希望这对将来的一些可怜的灵魂有所帮助。

于 2022-01-25T12:46:44.510 回答