tup*_*cat 3 c++ iokit macos-catalina macos-system-extension driverkit
我正在尝试与应用程序中的 ext 进行交互。我可以找到使用的服务,IOServiceOpen并且可以调用NewUserClient我的 dext(我可以看到type传递的参数在日志中输出)。在此之后我有点失落。阅读此处有关NewUserClient的内容 ,我可以看到应该使用它Create来创建一个新的 Service 对象。
这里的讨论部分说字典中的键propertiesKey描述了新服务。
是否应该将此字典作为顶级条目放置在系统扩展的 plist 文件中,还是应该将字典放在 key 中IOKitPersonalities?
我可以将IOServiceDEXTEntitlements密钥保留为空值,以便不对连接到系统扩展的应用程序施加任何权利限制吗?
我的 plist 看起来像这样(键MyUserClientProperties/字典在两个地方)。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>MyUserClientProperties</key>
<dict>
<key>IOClass</key>
<string>MyUserClient</string>
<key>IOUserClass</key>
<string>MyUserUSBInterfaceDriver</string>
<key>IOServiceDEXTEntitlements</key>
<string></string>
</dict>
<key>IOKitPersonalities</key>
<dict>
<key>example_device</key>
<dict>
<key>MyUserClientProperties</key>
<dict>
<key>IOClass</key>
<string>MyUserClient</string>
<key>IOUserClass</key>
<string>MyUserUSBInterfaceDriver</string>
<key>IOServiceDEXTEntitlements</key>
<string></string>
</dict>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>IOClass</key>
<string>IOUserService</string>
<key>IOProviderClass</key>
<string>IOUSBHostInterface</string>
<key>IOUserClass</key>
<string>MyUserUSBInterfaceDriver</string>
<key>IOUserServerName</key>
<string>sc.example.MyUserUSBInterfaceDriver</string>
<key>bConfigurationValue</key>
<integer>0x1</integer>
<key>bInterfaceNumber</key>
<integer>0x0</integer>
<key>idVendor</key>
<integer>0x123</integer>
<key>idProduct</key>
<integer>0x08</integer>
</dict>
</dict>
<key>OSBundleUsageDescription</key>
<string>Example user space USB driver</string>
</dict>
</plist>
Run Code Online (Sandbox Code Playgroud)
我需要SUPERDISPATCH作为最后一个参数传递给 吗Create?
来自“OSX 和 iOS 内核编程”第 5 章第 81 页:
I/O Kit 设计的巧妙之处在于用户客户端对象本身就是一个驱动程序对象:IOUserClient 类继承自 IOService,并且与任何其他 IOService 实例一样,每个用户客户端都有一个提供程序类,对于用户客户端来说,该提供程序类是应用程序正在控制的驱动程序的实例。
虽然上面的内容可能只适用于 kext (?),但我认为对于 dext 来说,事情的工作方式是相同的,
来自创建文档:使用 kIOUserClassKey 键指定您希望系统实例化的自定义 IOService 子类的名称。
为什么IOService需要实例化另一个类?这堂课的目的是什么?它是我的类继承自的提供者吗IOUserClient?如果是这样,我怎样才能使我的驱动程序的实例(实现的驱动程序NewUserClient)成为提供者?
从创建文档:使用指定要返回给服务客户端的kIOClassKey自定义子类的名称。IOUserClient
将创建并分配给 的第三个参数的类的类型是Create?如果是这样,那是我应该分配IOUserClient*指针并传递给的指针吗NewUserClient?
kern_return_t IMPL(MyUserUSBInterfaceDriver, NewUserClient) {
os_log(OS_LOG_DEFAULT, "%{public}d:", type);
IOPropertyName propertiesKey = "MyUserClientProperties";
IOService* client;
auto ret = Create(this, propertiesKey, &client, SUPERDISPATCH);
// Need to do more things here...
return ret;
}
Run Code Online (Sandbox Code Playgroud)
无论我尝试什么,我总是得到一个断言,但我看不出是什么原因造成的。
3 com.apple.DriverKit 0x0000000102f2b24b __assert_rtn + 102
4 com.apple.DriverKit 0x0000000102f2c20a IOService::Create_Impl(IOService*, char const*, IOService**) (.cold.2) + 35
5 com.apple.DriverKit 0x0000000102f1766b IOService::Create_Impl(IOService*, char const*, IOService**) + 91
6 com.apple.DriverKit 0x0000000102f2668f IOService::Create_Invoke(IORPC, OSMetaClassBase*, int (*)(OSMetaClassBase*, IOService*, char const*, IOService**)) + 135
7 com.apple.DriverKit 0x0000000102f276d7 IOService::Create(IOService*, char const*, IOService**, int (*)(OSMetaClassBase*, IORPC)) + 267
8 sc.example.MyUserUSBInterfaceDriver 0x0000000102ee0c89 MyUserUSBInterfaceDriver::NewUserClient_Impl(unsigned int, IOUserClient**) + 313 (MyUserUSBInterfaceDriver.cpp:155)
Run Code Online (Sandbox Code Playgroud)
尽管 DriverKit 的 WWDC 演示试图假装相反,但 DriverKit 的世界观与内核的世界观非常不同,您需要了解一些实现细节,因为抽象非常容易泄漏。
\n\n正如您可能已经发现的那样,IOServiceDriverKit 驱动程序中看起来像对象的实际上是一个IOUserServiceI/O 注册表的内核(和用户空间)视图中的对象。这个差距是通过 DriverKit 的 IPC 机制来弥补的。
为了创建新的用户客户端,您需要一个 (kernel)\xc2\xa0 子类的实例IOUserClient,该子类由 (dext) 子类支持IOUserClient。这个的内核类实际上是IOUserUserClient. (是的,确实如此。)正如您所发现的,文档并不完全清楚您如何进行此操作。我发现查看源代码方面的可用内容很有帮助 - 调用的内核端是在此处的函数NewUserClient 中实现的IOUserServer::serviceNewUserClient()。
您会立即注意到的一件事是,如果IOServiceDEXTEntitlements缺少该属性,这不会阻止代码成功:
prop = userUC->copyProperty(gIOServiceDEXTEntitlementsKey);\n ok = checkEntitlements(entitlements, prop, NULL, NULL);\nRun Code Online (Sandbox Code Playgroud)\n\n并在checkEntitlements:
if (!prop) {\n return true;\n }\nRun Code Online (Sandbox Code Playgroud)\n\n这是个好消息,因为这意味着我们暂时不需要担心它,可以简单地把它放在一边。
\n\n接下来,事实证明引用了提供者内核对象propertiesKey上的一个属性。您无法从 dext 的代码内部设置这些属性,因此提供它们的唯一方法是从 IOKit 匹配个性字典。IOUserService
您可以随意命名该属性,但是:
\n\n"IOClass"键值对,指定要实例化为字符串的内核类 - 在您的情况下,"IOUserUserClient""IOUserClass"键值对。这指定了要实例化的dext类,同样是一个字符串。在你的情况下,看起来像MyUserClient.把它放在一起:
\n\n <key>IOKitPersonalities</key> \n <dict>\n <key>example_device</key> \n <dict> \n <key>MyUserClientProperties</key>\n <dict>\n <key>IOUserClass</key>\n <string>MyUserClient</string>\n <key>IOClass</key>\n <string>IOUserUserClient</string>\n </dict>\n <key>CFBundleIdentifier</key>\n <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n \xe2\x80\xa6\n </dict>\n </dict>\n \xe2\x80\xa6\nRun Code Online (Sandbox Code Playgroud)\n\n然后,从您的NewUserClient函数中调用:
IOService* client = nullptr;\n kern_return_t ret = this->Create(this, "MyUserClient", &client);\nRun Code Online (Sandbox Code Playgroud)\n\n我认为SUPERDISPATCH这里不需要,因为您可能不会重写Create类中的方法,因此无论如何您的超级实现都会被继承。
然后进行错误检查、您可能需要的任何其他初始化、准备等,最后:
\n\n *userClient = client;\n return kIOReturnSuccess;\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
1434 次 |
| 最近记录: |