【问题标题】:How to match linux device path to windows drive name?如何将 linux 设备路径与 Windows 驱动器名称匹配?
【发布时间】:2010-09-06 08:18:19
【问题描述】:

我正在编写一个在 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 系统调用)、块数(来自 /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 应用程序?

附:应用程序的语言是 C++。我无法改变这一点。

【问题讨论】:

    标签: c++ linux drives


    【解决方案1】:

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

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

    如果 Windows 中有一个等效的功能,您可以简单地存储他们选择的任何分区的 UUID,然后遍历 linux 中的所有已知分区并匹配 UUID。

    编辑:这可能是一个仅限 linux 的东西,它可能是从某些东西生成这些的 volid 实用程序(而不是读取驱动器的元数据)。话虽如此,没有什么能阻止您获取 volid 的源代码并查看它的作用。

    【讨论】:

      【解决方案2】:

      分区有与之关联的 UUID

      我对此的了解非常浅薄,但我认为这仅适用于使用 GPT(Guid Partition Table)分区格式化的磁盘,而不是世界上 99% 仍然坚持使用的旧式 MBR 格式?

      【讨论】:

        【解决方案3】:

        我这方面的知识很浅薄, 但我认为这仅适用于 使用 GPT 格式化的磁盘(Guid 分区表)分区,而不是 比旧式的 MBR 格式 世界上 99% 的人还在坚持吗?

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

        【讨论】:

          【解决方案4】:

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

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

          在 Linux 中做 GUI 工作要比尝试这种混合的 Window/Linux 解决方案容易得多。我不是说不要这样尝试,我要说的是这种方法有很多可能的陷阱。我敢肯定,我什至都不知道所有这些。

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

          因此,如果可以的话,我想再重复一遍,看看您是否可以在 Linux 中做所有事情。从长远来看,它会简单得多。

          【讨论】:

            【解决方案5】:

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

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

            如果 Windows 中有一个等效的功能,您可以简单地存储他们选择的任何分区的 UUID,然后遍历 linux 中的所有已知分区并匹配 UUID。

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

            【讨论】:

              【解决方案6】:

              在 Windows 中,您可以读取与 Linux 下的 UUID 相匹配的“NTFS 卷序列号”。

              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

              【讨论】:

                猜你喜欢
                • 2021-10-14
                • 1970-01-01
                • 1970-01-01
                • 2018-06-27
                • 1970-01-01
                • 2018-11-22
                • 2011-09-02
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多