Mount/Unmount 来自 macOS 内核扩展的文件系统

Mount/Unmount filesystem from macOS kernel extension

hdiutil 可以将包含 HFS+ 分区的 DMG 文件附加和分离到选定的挂载点。但是,它使用了 DiskImages.framework 的私有 API。我的目标是使这个任务完全可编程,所以我在内核驱动领域寻找替代方案。

在深入研究由 <sys/mount.h> 表示的 KPI 时,我发现根据其匹配的 fsid 卸载文件系统的有用方法:

int vfs_unmountbyfsid(fsid_t *fsid, int flags, vfs_context_t ctx)

但是我们mount有相反的操作吗?

启动挂载没有 public KPI,我什至不知道 com.apple.kpi.private 中的函数。然而,在用户 space 中,您可以使用的不仅仅是 DiskImages.framework:有 DiskArbitration.framework,当然还有 mount(2) 的 POSIX 系统调用。

我认为您可能在这里混淆了 2 个概念,它们实际上是完全不同的:

  1. 打开磁盘映像并创建虚拟块设备以访问其内容
  2. 正在块设备上安装文件系统。

磁盘映像支持不是 xnu 内核的固有部分。它们在 IOHDIXController 对象中实现(此代码在 kext 中),您会发现它附加到 IORegistry 中的 IOResources。当用户 double-clicks 一个 .dmg 文件或类似文件时,diskimages-helper 守护程序打开并解析它并指示 IOHDIXController 创建一个新的 IODiskImageBlockStorageDeviceOutKernel 实例(一个 IOBlockStorageDevice 子类)。这对 OS 来说就像一个物理块设备,通常的堆栈 IOBlockStorageDriver -> IOMedia -> IOPartitionScheme -> IOMedia -> IOMediaBSDClient 对象在其之上配置自身。然后这会导致设备发现事件在 diskarbitrationd 中触发,这会继续到过程的第二部分:在新发现的 IOMedia 对象的 /dev/diskXsY 节点上调用 mount(2)( s) 视情况而定。

据我所知,HDIX 子系统尚未开放。因此,如果您想实现自己的磁盘映像格式,则需要重新创建类似于 Apple 的 diskimage-helperIOHDIXController.kext 的内容。如果您愿意,您可以完全实施它 in-kernel,尽管这可能不是一个好主意。

第二部分,安装,如果您使用 IOStorage 堆栈,则由 diskarbitrationd 自动完成,但您可以通过磁盘仲裁异议者影响它。有关详细信息,请参阅 DiskArbitration.framework。但这也可以让你影响 diskimages-helper 处理的磁盘映像的挂载,所以如果你使用它支持的映像格式,你将不需要编写自己的并且可以简单地拦截挂载并做任何事情你想自己做。

您也可以完全绕过 IOStorage 堆栈,只在您的 kext 中创建 BSD 开发节点。在这种情况下,diskarbitrationd 应该不会注意到它,您需要从守护进程中显式调用 mount()

我希望这能澄清事情。