“NewUserClient”应该如何实现

2023-12-04

我正在尝试与应用程序中的 ext 进行交互。我可以使用找到该服务IOServiceOpen我接到电话NewUserClient我的 dex(我可以看到type传递的参数正在日志中输出)。在此之后我有点失落。在这里阅读有关新用户客户端我可以看到应该使用Create创建一个新的服务对象。

讨论部分here says 中的按键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>  

我需要通过吗SUPERDISPATCH作为最后一个参数Create?

来自“OSX 和 iOS 内核编程”第 5 章第 81 页:

I/O Kit 设计的巧妙之处在于用户客户端对象本身就是一个驱动程序对象:IOUserClient 类继承自 IOService,并且与任何其他 IOService 实例一样,每个用户客户端都有一个提供程序类,对于用户客户端来说,该提供程序类是应用程序正在控制的驱动程序的实例。

虽然上面的内容可能只适用于 kext (?),但我认为对于 dext 来说,事情的工作方式是相同的,

From Create文档:使用 kIOUserClassKey 键指定您希望系统实例化的自定义 IOService 子类的名称。

为什么是另一个IOService类需要实例化吗?这堂课的目的是什么?我的类的提供者是否继承自IOUserClient?如果是这样,我怎样才能创建我的驱动程序的实例(实现NewUserClient) 提供者?

From Create文档:Use the 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;  
}  

无论我尝试什么,我总是得到一个断言,但我看不出是什么原因造成的。

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)

尽管 DriverKit 的 WWDC 演示试图假装相反,但 DriverKit 的世界观与内核的世界观非常不同,您需要了解一些实现细节,因为抽象非常容易泄漏。

正如您可能已经发现的那样,看起来像IOServiceDriverKit 驱动程序中的对象实际上是一个IOUserServiceI/O 注册表的内核(和用户空间)视图中的对象。这个差距是通过 DriverKit 的 IPC 机制来弥补的。

为了创建一个新的用户客户端,您需要一个(内核)的实例IOUserClient子类,由您的 (dext) 支持IOUserClient子类。这个的内核类实际上是IOUserUserClient。 (是的,确实如此。)正如您所发现的,文档并不完全清楚您如何进行此操作。我发现查看源代码中可用的内容(调用的内核部分)很有帮助NewUserClient 实施于IOUserServer::serviceNewUserClient()在这里发挥作用.

您会立即注意到的一件事是,如果IOServiceDEXTEntitlements属性丢失,这不会阻止代码成功:

            prop = userUC->copyProperty(gIOServiceDEXTEntitlementsKey);
            ok = checkEntitlements(entitlements, prop, NULL, NULL);

and in checkEntitlements:

    if (!prop) {
        return true;
    }

这是个好消息,因为这意味着我们暂时不需要担心它,可以简单地把它放在一边。

接下来,事实证明,propertiesKey指的是一个属性在提供者上IOUserService内核对象。您无法从 dext 代码内部设置这些属性,因此提供它们的唯一方法是从 IOKit 匹配个性字典中。

您可以随意命名该属性,但是:

  • 它的值必须是一个字典。
  • 它必须包含"IOClass"键值对,指定kernel类实例化为字符串 - 在你的情况下,"IOUserUserClient"
  • 它必须包含"IOUserClass"键值对。这指定了dext要实例化的类,再次作为字符串。在你的情况下,看起来像MyUserClient.

把它放在一起:

  <key>IOKitPersonalities</key>  
  <dict>
    <key>example_device</key>  
    <dict>  
      <key>MyUserClientProperties</key>
      <dict>
        <key>IOUserClass</key>
        <string>MyUserClient</string>
        <key>IOClass</key>
        <string>IOUserUserClient</string>
      </dict>
      <key>CFBundleIdentifier</key>
      <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
      …
    </dict>
  </dict>
  …

然后,从你的NewUserClient函数,调用:

    IOService* client = nullptr;
    kern_return_t ret = this->Create(this, "MyUserClient", &client);

我不相信SUPERDISPATCH这里需要,因为你可能不会覆盖Create方法在你的类中,所以你的超级实现无论如何都会被继承。

然后进行错误检查、您可能需要的任何其他初始化、准备等,最后:

    *userClient = client;
    return kIOReturnSuccess;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

“NewUserClient”应该如何实现 的相关文章

随机推荐