【问题标题】:Develop a userspace read-only disk driver for macOS为 macOS 开发用户空间只读磁盘驱动程序
【发布时间】:2020-09-19 00:24:21
【问题描述】:

我有一种特殊的磁盘映像格式(压缩并带有坏块等额外信息),并希望在 macOS 中将其作为块设备(例如在/dev/rdisk 下)提供。

我正在寻找有关如何编写只读块级用户空间驱动程序的指针。

我认为我需要使用 IOKit 来执行此操作,但该领域的文档非常稀少,据我所知没有提供任何示例代码。

我查看了 Amit Singh 的 Mac OS Internals,但这只涉及过滤通过添加的驱动程序路由的现有块。但是我需要从一个单独的文件中读取数据,即我需要使用文件系统,如果可能的话,我还想在用户空间应用程序中执行此操作,因为制作 kext 既难以调试,现在也被弃用了.

理想情况下,这应该适用于当前的 macOS 版本,包括 10.15,但我也很高兴有一个仅适用于旧 macOS 版本的解决方案,从 10.6 开始。

也许我在这里仍然误解了一些事情。我的印象是甚至在 10.15 之前就可以编写用户空间 IOKit 驱动程序。但也许这对于块存储设备是不可能的?欢迎任何澄清。我感到很失落。

2020 年 6 月 22 日更新

我也在 OSXFUSE 支持论坛上问过这个问题,并在那里得到了negative reply

【问题讨论】:

    标签: macos disk iokit


    【解决方案1】:

    也许我在这里仍然误解了一些事情。我的印象是甚至在 10.15 之前就可以编写用户空间 IOKit 驱动程序。

    这是一个真实的陈述,但这并不意味着可以在用户空间中编写所有类型的驱动程序,即使是 10.15。混淆可能源于“IOKit”在不同的上下文中被用来表示微妙的不同事物:

    • 从根本上说,它是基于 OOP 的驱动堆栈技术,内置在 XNU 内核(macOS、iOS 等)中,用 C++ 编写。它的核心数据结构是 I/O Kit 注册表,它是代表设备、设备(子)功能、虚拟设备、服务、驱动程序、用户空间客户端连接等的对象的有向图(大部分具有以下属性)它,但从技术上讲,节点可以有多个“父”节点,有些实际上是在典型的 Mac 系统上这样做的)
    • IOKit 用户空间库。 (a.k.a. IOKit.framework a.k.a. IOKitLib + 各种 IOCFPlugins)这些为用户空间程序提供了内核 I/O 注册表的视图,并允许它们与 IOKit 对象执行某些交互。这基本上限于:
      • 迭代注册表图并根据匹配规则匹配服务。两者都将特定 I/O 注册表项的句柄返回给用户空间程序。
      • 获取 I/O 注册表项的属性,如果对象明确支持它,则设置(某些)属性。
      • 创建用户客户端连接。这是从常规用户空间在 I/O 注册表中创建条目的唯一方法,并且这些始终是 IOUserClient 子类,并且只有在父对象明确允许的情况下。
    • IOKit 视图可用于基于 DriverKit 的系统扩展进程(10.15 中的新功能),它允许实例化完全支持用户空间的注册表项对象,用于子类化(有界)选择的超类类型。

    回答您具体案例的问题:

    • 要实现一个块存储设备的驱动程序,该驱动程序将在系统中显示为任何其他设备,您需要子类化IOStorage 或其子类之一(通常为IOBlockStorageDevice)。
    • IOKit.framework 允许您创建由该用户空间进程或其他用户空间进程使用的用户空间驱动程序。 因此不可能使用它来创建将被内核的某些部分使用的驱动程序。例如,无法创建将被内核的 VFS 系统使用的块设备驱动程序。
    • DriverKit 目前(从 macOS 10.15.4 SDK 开始)不允许任何存储堆栈类的 dext 支持的子类。所以 dext 并不能解决问题。
    • 据我所知,做你想做的事情的唯一方法是拥有一个由两部分组成的驱动程序:一个实现 IOBlockStorageDevice 子类的 kext,以及一个提供用于连接某些用户空间进程的用户客户端接口,用于创建块设备实例,并将处理设备的 I/O 请求。这有点类似于在 VFS 层而不是块层工作的 FUSE 机制。
      这正是 macOS 的内置磁盘映像挂载系统的工作原理。不幸的是,其中的 kext 和用户空间部分都不是开源的、文档化的或公共 API。因此,除非您对其进行逆向工程并找到不强制要求 Apple 代码签名的边界,否则您基本上必须重新实现它。

    我目前不知道有一个现有的开源系统可以做到这一点,但我没有仔细研究过。特别是对于只读访问,如果您知道自己在做什么,应该不会很难做到,但它会带来开发和分发 kexts 的常见缺点。

    请注意,如果它所代表的块设备托管您希望挂载的文件系统,并且存在该文件系统的 FUSE 实现,您也可以使用 FUSE 打开磁盘映像。

    【讨论】:

    • 非常感谢您的广泛回复。是的,我一直试图找到 hdiutil 源,但也没有成功。我会考虑用 FUSE 解决这个问题,因为这听起来是最简单的方法,我正在寻找一种用于特殊用途的简单解决方案(不一定对公众开放)。
    • 我认为可能还有一个选择:据我所知,macOS 支持连接到 iSCSI 目标,因此如果您要在 localhost 上运行的进程中实现该 iSCSI 目标,我认为应该工作。不过,我从未尝试过!
    猜你喜欢
    • 2011-01-11
    • 2020-10-09
    • 1970-01-01
    • 2018-06-18
    • 2011-07-19
    • 2014-12-01
    • 2017-01-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多