如何将linux设备路径与Windows驱动器名称匹配?

时间:2020-03-05 18:41:19  来源:igfitidea点击:

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

  • 在Windows中将分区信息(即驱动器号,块数,驱动器序列号等)存储在某个预定义的位置(即系统分区的根目录)中。
  • 从/ proc / partitions中读取分区列表。仅获取具有SCSI或者IDE硬盘驱动器主编号和将其标识为实际分区而不是整个磁盘的次编号的那些分区。
  • 尝试使用ntfs或者vfat文件系统挂载它们中的每一个。检查安装的分区是否包含Windows应用程序存储的信息。
  • 找到Windows应用程序编写的必需信息后,进行实际匹配。对于在/ proc / partitions中找到的每个分区,获取驱动器序列号(通过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驱动器。
  • / sys / block hack可能不适用于IDE或者SATA驱动器。

关于如何改进此架构的任何想法?也许还有另一种方法可以确定Windows名称而无需在Windows应用程序中写入所有数据?

P.S.该应用程序的语言是C ++。我不能改变这个。

解决方案

回答

分区具有与之关联的UUID。我不知道如何在Windows中找到这些,但是在Linux中,我们可以使用以下命令找到每个分区的UUID:

sudo vol_id -u device (e.g. /dev/sda1)

如果Windows中具有等效功能,则可以简单地为它们选择的任何分区存储UUID,然后遍历Linux中所有已知的分区并匹配UUID。

编辑:这可能是仅限Linux的事情,并且它可能特别是从某些东西生成这些内容的volid util(而不是读取驱动器的元数据)。话虽这么说,没有什么能阻止我们获得volid的来源并检查它的作用。

回答

Partitions have UUIDs associated with them

我对此的知识很浅,但是我认为这仅适用于使用GPT(Guid分区表)分区格式化的磁盘,而不适用于仍然有99%的世界使用的老式MBR格式?

回答

My knowledge of this is very shallow,
  but I thought that was only true for
  disks formatted with GPT (Guid
  Partition Table) partitions, rather
  than the old-style MBR format which
  99% of the world is still stuck with?

听起来不像是Linux用户老套,但它对我有用。就像我在编辑中所说的那样,vol_id可能是自己生成的。如果是这样的话,将不会依赖任何特定的分区格式,这会膨胀。

回答

我们需要以某种方式标记驱动器(例如,写入文件等),或者找到一些仅与该特定驱动器相关联的标识符。

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

在Linux内部做GUI东西比尝试这种混合的Window / Linux解决方案要容易得多。我并不是说不要尝试这种方式,我是说这种方法有很多可能的陷阱。我确定我什至都不知道所有这些。

另一个选择是查看我们是否真的可以在Windows内部执行Linux部分。如果我们是一个非常出色的Windows程序员,则实际上可以访问原始文件系统。这种方法可能有很多陷阱,因为在所有这些操作期间,Windows都将运行。

因此,我再次重申一下,如果可以的话,我们是否可以在Linux内完成所有操作。从长远来看,这只是简单得多。

回答

Partitions have UUIDs associated with them. I don't know how to find these in Windows but in linux you can find the UUID for each partition with:
  
  
    sudo vol_id -u device (e.g. /dev/sda1)

如果Windows中具有等效功能,则可以简单地为它们选择的任何分区存储UUID,然后遍历Linux中所有已知的分区并匹配UUID。

很好,谢谢!我查看了vol_id(udev tarball的一部分)的来源,似乎对于FAT(32)和NTFS,它使用从分区上预定义位置读取的卷序列号生成UUUD。由于除了fat32和ntfs之外,我什么都不期望了,因此我考虑将这些信息用作分区标识符。

回答

在Windows中,我们可以阅读" NTFS卷序列号",其接缝与Linux下的UUID匹配。

从Windows获得" NTFS卷序列号"的可能性:

  • XP以后的命令行:fsutil.exe fsinfo ntfsinfo C:
  • 在C ++下
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;

在Linux下获取UUID的可能性:

  • ls -l / dev / disk / by-uuid
  • ls -l / dev / disk / by-label
  • blkid / dev / sda1