在Mac OS X上打开磁盘设备文件以进行写访问

5

我正在尝试对Mac上的磁盘分区表进行微小的修改;特别是,我需要更改分区的类型。 diskutil 不支持此操作,因此我无法使用它。如果磁盘未在使用中,则可以正常工作(例如通过修改的 gpt 命令行实用程序)。如果正在使用,则在打开设备文件时失败:

int fd = open("/dev/disk1", O_RDWR);

fd是-1,errno指示错误“资源繁忙”。

我意识到可以从不同的驱动器重新启动计算机,然后修改原始磁盘,然后再次启动。然而,这并不容易自动化/可靠地从我的应用程序内部进行。此外,diskutil没有问题编辑活动设备的分区表,引导助理也是如此。

有已知的方法吗?最坏的情况下,我可以尝试在内核中执行此操作,但是kext并不真正设计用于执行一次性操作,而我需要在用户空间中非常简单但在内核中却相当困难。

有什么想法吗?

注意:我使用sudo运行所有内容,因此不应该是权限问题。


你看过fdisk的源代码了吗? - KevinDTimm
fdisk在我测试过的任何Mac上都无法正常工作。它试图打开一个不存在的文件/usr/standalone/i386/boot0。即使不考虑这一点,它似乎也没有做任何聪明的事情。 - pmdj
好的,如果不是fdisk,那么就是freebsd的等效工具(我猜测苹果会为他们的磁盘工具提供前端界面)。 - KevinDTimm
Intel Macs默认使用GUID分区方案,因此我尝试使用gpt实用程序进行实验,该实用程序源自BSD。然而,diskutil似乎不是gpt的前端,正如我之前提到的,gpt实际上并不能正常工作。diskutil的源代码不可用。 - pmdj
2个回答

8

苹果是如何做到的

通过使用otool和反汇编器进行一些侦查后,我确定苹果的diskutil使用了一些私有框架来完成任务。(我看过命令行版本,但GUI Disk Utility的功能集和状态/错误消息与之如此相似,我怀疑它们之间没有区别) 特别是,Objective-C DiskManagement.framework包含类和方法,这些类和方法与diskutil命令一一映射。许多错误消息似乎来自于不基于 Objective-C 的MediaKit.framework,因此在otool中看不到其API。

简要地浏览了某些函数的反汇编结果后,似乎大量使用了 Mach Ports 和 MIG。我不知道逆向工程的兔子洞究竟有多深,以及是否会带来实用价值。毕竟,DiskManagement.framework似乎正好做到了diskutil所做的一切,而且并不包括直接编辑分区表。即使我找到了它的内部原理,那也可能无法帮助我解决问题。

我的做法

因此,为了避免浪费更多的时间在成功机会存疑的活动上,我最终还是通过内核扩展来完成这个任务,这正是我试图避免的。我基本上构建了一个通用的IOService子类以及一个IOUserClient配套的子类。这些子类公开了一些方法,用于将现有的分区表替换为新的分区表,并运行为根用户空间进程。它会搜索与设备名称对应的IOMedia对象,然后通过一些技巧直接对其进行读/写操作。我向其中传递旧的分区表,以便它可以验证是否确实更新了正确的内容。在用户空间方面,我修改了gpt实用程序,以使用用户空间I/O Kit库与内核扩展通信。我仅在进行更改时暂时加载内核扩展,然后再次卸载它。这花费我大约两天时间,但效果很好。


-1

你需要使用原始磁盘设备 - 在你的情况下,应该是/dev/rdisk1。此外,显然,你需要成为root用户。


我使用rdiskdisk都会出现“资源繁忙”的错误。对于未被使用的磁盘,两者都可以正常工作。是的,我正在使用sudo(否则我会收到权限错误而不是“资源繁忙”)。 - pmdj
1
好的,那么请确保卸载该磁盘上的所有卷。如果它是您的启动磁盘(我不敢想象 ;),则可能需要从OS X DVD引导。 - Simon Urbanek
哪个磁盘是由用户决定的,主引导磁盘将是一个受欢迎的选择。这一切都与安装在旁边的(内核)驱动程序相关联。除非分区类型匹配,否则驱动程序不会加载,因此我想避免为重新分区编写另一个内核模块。看起来我不得不这样做。 - pmdj

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接