使用 C/C++ 访问 RAW 磁盘

Posted

技术标签:

【中文标题】使用 C/C++ 访问 RAW 磁盘【英文标题】:Access the RAW disk using C/C++ 【发布时间】:2015-01-19 03:17:11 【问题描述】:

我有一个大型存储设备(闪存)通过 PCIe 总线插入到我的计算机上,我想直接访问这样的设备,即它上面没有任何文件系统(例如 NTFS 或 ext4)。

如何使用 C/C++ 做到这一点? (在 Windows 7 和 Linux 上) 我想知道我是否可以 1) 将设备作为文件打开,然后对其读写二进制数据,或者 2) 使用 malloc 之类的函数分配整个设备,然后设备上的每个字节都有一个地址这样我就可以根据地址访问它们。

如果可能的话,我更喜欢第二种方式,但我不知道操作系统是否支持这种方式,因为似乎地址空间需要与主内存共享。

【问题讨论】:

不了解 Windows,但 mmap() 是您在 Linux 上寻找的。​​span> 低级硬件支持是您可以在操作系统的 API 中找到的那种东西,而不是在标准 C/C++ 库中。 您手头有操作系统吗?如果是,是哪一个? @πάνταῥεῖ 我有 win7 和 Ubuntu 12.04 服务器 @xbug, CreateFileMapping 类似于mmap。这些方法用于文件映射到用户进程的地址空间,与设备无关。 【参考方案1】:

据微软documentation:

在 Windows 上,您可以使用CreateFile 使用表单路径打开物理驱动器

\\.\PhysicalDriveN

其中N 是设备号或使用路径形式的逻辑驱动器

\\.\X:

您将需要以扇区大小的倍数查找、读取和写入,可以使用 DeviceIoControl() 和 IOCTL_DISK_GET_DRIVE_GEOMETRY 检索。

【讨论】:

好像文档不够详细,如何定位磁盘中的块或扇区? 定位是什么意思?您只需寻找您想要在打开的文件中定位扇区 * 扇区大小的任何扇区。【参考方案2】:

在 Linux 上,每个存储设备最终都会在 /dev 中获得一个设备条目。第一个存储设备通常是/dev/sda,第二个存储设备(如果存在)是/dev/sdb。请注意,光盘是一种存储设备,因此 CD-ROM 或 DVD-ROM 驱动器(如果存在)将获得设备节点条目。

一些 Linux 发行版可能使用不同的命名约定,但通常是这样。因此,您需要确定与您的闪存盘对应的设备,然后打开/dev/sdX 设备,然后简单地从中读取和写入。您的读取和写入必须是偶数块(扇区)大小,并且查找打开的文件决定了后续读取或写入将影响哪些磁盘块/扇区。

通常,/dev/sdX 将归 root 所有,但通常有一些特定于 Linux 发行版的方法来调整拥有特定设备节点的用户 ID。

【讨论】:

我明白了。所以我不可能以字节为单位但以扇区为单位访问,对吧?在内存中,我可以使用地址来定位一个字节,那么如何在磁盘中定位一个扇区呢? 磁盘上的第一个扇区(嗯,第 0 个扇区)的字节偏移量为 0,下一个扇区的字节偏移量为 512,依此类推...您将文件查找到正确的偏移量,对于你的逻辑块地址,并读取块。

以上是关于使用 C/C++ 访问 RAW 磁盘的主要内容,如果未能解决你的问题,请参考以下文章

windows2012 R2群集的磁盘变raw无法格式化的解决

KVM之raw和qcow2格式虚拟磁盘创建

linux下挂载VHD等虚拟磁盘文件

监控磁盘大小c语言

KVM--磁盘+快照+克隆+网络管理

KVM虚拟化平台——磁盘管理