C++ 如何将linux设备路径与windows驱动器名匹配?

C++ 如何将linux设备路径与windows驱动器名匹配?,c++,linux,drives,C++,Linux,Drives,我正在编写一个应用程序,它在Linux环境中的某些阶段执行低级磁盘操作。该应用程序实际上由两部分组成,一部分运行在Windows上并与用户交互,另一部分是从LiveCD运行的linux部分。用户选择Windows驱动器号,然后linux部件使用相应的分区执行操作。问题是在Windows驱动器号(如C:)和linux设备名(如/dev/sda1)之间找到匹配项。这是我目前认为难看的解决方案: 将分区信息(即驱动器号、块数、驱动器序列号等)存储在Windows中的某个预定义位置(即系统分区的根目录

我正在编写一个应用程序,它在Linux环境中的某些阶段执行低级磁盘操作。该应用程序实际上由两部分组成,一部分运行在Windows上并与用户交互,另一部分是从LiveCD运行的linux部分。用户选择Windows驱动器号,然后linux部件使用相应的分区执行操作。问题是在Windows驱动器号(如C:)和linux设备名(如/dev/sda1)之间找到匹配项。这是我目前认为难看的解决方案:

  • 将分区信息(即驱动器号、块数、驱动器序列号等)存储在Windows中的某个预定义位置(即系统分区的根目录)

  • 从/proc/partitions读取分区列表。仅获取具有SCSI或IDE硬盘驱动器主编号和将其标识为真实分区的次编号的分区,而不是整个磁盘

  • 尝试使用ntfs或vfat文件系统装载它们中的每一个。检查装入的分区是否包含Windows app存储的信息

  • 找到Windows应用程序写入的所需信息后,进行实际匹配。对于在/proc/partitions acquire驱动器序列号(通过HDIO_GET_IDENTITY syscall)、块数(来自/proc/partitions)和驱动器偏移量(/sys/blocks/drive_path/partition_name/start)中找到的每个分区,将其与Windows信息进行比较,如果匹配,则将Windows驱动器号与linux设备名一起存储

该方案存在两个问题:

  • 这太难看了。在Windows中写入数据,然后在Linux中读取数据,这使得测试成为一场噩梦

  • linux设备主要编号仅与IDE或SCSI设备进行比较。这可能会失败,即在USB或FireWire磁盘上。可以添加这些类型的磁盘,但将应用程序限制在已知的可能设备子集似乎是一个相当糟糕的主意

  • 看起来HDIO_GET_IDENTITY仅适用于IDE和SATA驱动器

  • /除IDE或SATA驱动器外,sys/block hack可能无法在其他驱动器上工作

关于如何改进这个模式有什么想法吗?也许有另一种方法可以确定windows名称,而无需在windows应用程序中写入所有数据


P.S.语言的应用程序是C++。我无法更改此设置。

分区具有与之关联的UUID。我不知道如何在Windows中找到这些,但在linux中,您可以通过以下方式找到每个分区的UUID:

sudo vol_id-u设备(例如/dev/sda1)

如果Windows中有一个等价函数,那么您可以简单地为它们选择的任何分区存储UUID,然后在linux中迭代所有已知分区并匹配UUID

编辑:这可能是linux独有的功能,它可能是从某个内容生成这些内容的volid util(而不是读取驱动器的元数据)。话虽如此,没有什么能阻止您获取volid的源代码并检查它的功能


分区具有与其关联的UUID

我对这方面的了解很肤浅,但我认为这只适用于使用GPT(Guid分区表)分区格式化的磁盘,而不是99%的世界仍然使用的旧式MBR格式

我对这方面的了解很肤浅, 但我认为这只适用于 使用GPT(Guid)格式化的磁盘 分区表)分区,而不是 比老式的MBR格式 世界上99%的人仍然被这种疾病困扰着


听起来不像是linux用户的陈词滥调,但它对我很有用。。我在NTFS分区中使用它,没有任何问题。正如我在编辑中所说,volu_id可能是自己生成的。如果是这种情况,就不会依赖于任何特定的分区格式,这将是一种膨胀。

您需要以某种方式标记驱动器(例如,写入文件等),或者查找仅与该特定驱动器关联的标识符

在不运行Windows的情况下,很难、几乎不可能弄清楚Windows将分配给特定驱动器分区的字母。这是因为Windows总是将运行它的驱动器与C:相关联。如果安装了多个操作系统,则可以是任何驱动器。Windows还允许您为特定分区选择它将首先尝试的驱动器号,从而导致进一步的问题

在Linux内部进行GUI工作要比尝试这种混合窗口/Linux解决方案容易得多。我不是说不要这样做,我是说这种方法有很多可能的陷阱。我肯定我甚至不知道所有这些

另一个选择是看看你是否真的可以在Windows中完成Linux部分。如果你是一个非常优秀的Windows程序员,你实际上可以访问原始文件系统。这种方法可能也存在同样多的陷阱,因为Windows将在所有这些都运行时运行

因此,为了重新迭代,我想看看您是否可以在Linux中完成所有工作,如果可以的话。从长远来看,这要简单得多


分区具有与其关联的UUID。我不知道如何在Windows中找到这些,但在linux中,您可以通过以下方式找到每个分区的UUID:

sudo vol_id-u设备(例如/dev/sda1)

如果Windows中有一个等价函数,那么您可以简单地为它们选择的任何分区存储UUID,然后在linux中迭代所有已知分区并匹配UUID

这是一个很好的观点,谢谢!我查看了volu id(udev tarball的一部分)的来源,似乎对于FAT(32)和NTFS,它使用从分区上预定义位置读取的卷序列号生成UUUD。因为我不期待任何其他的FAT32和NTFS,我考虑使用这个信息。
HANDLE fileHandle = CreateFile(L"\\\\.\\C:", // or use syntax "\\?\Volume{GUID}" 
                               GENERIC_READ,
                               FILE_SHARE_READ|FILE_SHARE_WRITE,
                               NULL,
                               OPEN_EXISTING,
                               NULL,
                               NULL);
DWORD i;
NTFS_VOLUME_DATA_BUFFER ntfsInfo;
DeviceIoControl(fileHandle, 
                FSCTL_GET_NTFS_VOLUME_DATA, 
                NULL, 
                0, 
                &ntfsInfo,
                sizeof(ntfsInfo), 
                &i, 
                NULL));
cout << "UUID is " << std::hex << ntfsInfo.VolumeSerialNumber.HighPart << std::hex << ntfsInfo.VolumeSerialNumber.LowPart << endl;