我正在编写一个应用程序,该应用程序在某个阶段在 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 驱动器以外的其他驱动器。

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

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

有帮助吗?

解决方案

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

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

如果 Windows 中有等效的函数,您可以简单地存储它们选择的任何分区的 UUID,然后迭代 Linux 中的所有已知分区并匹配 UUID。

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

其他提示

分区具有与其关联的 UUID

我对此的了解很浅,但我认为这只适用于使用 GPT(引导分区表)分区格式化的磁盘,而不是世界上 99% 的人仍然坚持使用的旧式 MBR 格式?

我对此的了解非常浅,但是我认为这仅是用GPT(GUID分区表)分区格式化的磁盘,而不是旧风格的MBR格式,世界上99%的99%仍在粘住?

听起来不像是 Linux 用户的陈词滥调,但它对我有用。我在 NTFS 分区上使用它,没有遇到任何问题。正如我在编辑中所说,vol_id 可能会自行生成它们。如果是这样的话,就不会依赖任何特定的分区格式,这将是膨胀的。

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

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

如果 Windows 中有等效的函数,您可以简单地存储它们选择的任何分区的 UUID,然后迭代 Linux 中的所有已知分区并匹配 UUID。

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

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

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

在 Linux 中完成 GUI 工作比尝试这种混合 Window/Linux 解决方案要容易得多。我并不是说不要尝试这种方式,我的意思是这种方法有很多可能的陷阱。我确信我什至都不知道他们所有人。

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

因此,重申一下,如果可以的话,我想看看您是否可以在 Linux 中完成所有操作。从长远来看,这要简单得多。

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

可以从以下位置获取“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;
    

获取 UUID 的可能性 Linux:

  • ls -l /dev/disk/by-uuid
  • ls -l /dev/disk/by-label
  • blkid /dev/sda1
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top