假设我有一只鼠标。我将这只鼠标插入电脑上 4 个插槽中的 1 号。它会检测新设备,一切正常。但如果我稍后带着同一只鼠标回来,并将其插入插槽 3,它会再次进行检测!为什么会这样?
答案1
根据陈瑞文:
为什么当我将 USB 设备插入不同的端口时,Windows 无法将其识别为同一设备?
您可能已经注意到,如果您将 USB 设备插入计算机,Windows 会识别并配置它。然后,如果您将其拔出并重新插入另一个 USB 端口,Windows 就会失去记忆,认为这是一个完全不同的设备,而不是使用您上次插入时应用的设置。这是为什么呢?
USB 设备人员解释说,当设备缺少 USB 序列号时就会发生这种情况。
USB 设备上的序列号是可选的。如果设备有序列号,则无论将其插入哪个 USB 端口,Windows 都会识别该设备。但如果设备没有序列号,则 Windows 会将每次出现在不同 USB 端口上的设备都视为新设备。
(我记得有一家主要的 USB 设备制造商不太了解序列号的工作原理。他们为所有设备都提供了序列号,这很好,但它们都获得了相同的序列号。如果您同时将两个设备插入计算机,就会发生令人兴奋的事情。)
但是,如果设备没有序列号,并且出现在不同的端口上,为什么 Windows 会将其视为不同的设备呢?为什么它不能直接说“哦,你在那里,在另一个端口上。”
因为一旦插入两个这样的设备,就会产生随机行为。根据即插即用枚举设备的顺序,两组设置将在每次启动时随机分配。今天设置以一种方式匹配,但明天当设备以另一种顺序枚举时,设置就会交换。(如果您以不同的顺序插入设备,您也会得到类似的令人困惑的行为。)
换句话说:事情之所以糟糕,是因为 (1) 事情本来就很糟糕 — 如果设备有正确的序列号,这不会成为问题 — 并且 (2) 一旦处于这种糟糕的状态,替代方案会更糟糕。USB 堆栈只是试图在不让情况变得更糟的情况下做到最好。
答案2
Windows(由于您没有说明您的操作系统,我假设您正在使用操作系统)将设备与其插入的端口关联,因此它认为“端口 X 中的 USB DISK A”不同于“端口 Y 中的 USB DISK A”,并且它会相应地链接驱动程序和注册表项。
如果您在查看设备管理器时使用“显示未连接的设备”选项,您将看到该设备连接到它曾经插入过的所有端口,但由于它当前不在这些端口中,因此显示为灰色。当您将设备插入其中一个端口时,Windows 将激活该驱动程序实例,当您将其插入另一个端口时,它需要为该端口定义一个新的驱动程序实例,然后才能激活它(这是您作为用户看到的显示为“添加新设备”的过程)。
这样,您可以将相同的设备插入不同的端口,同时工作。还有其他方法可以实现这一点,对于最终用户来说,操作系统使用哪种技术几乎没有实际区别,但这就是 Windows 选择的方式。
答案3
如果设备有序列号,它就不会这样做。但是,为什么当子设备出现在不同的端口上时,Windows 驱动程序会为其分配不同的实例 ID,以至于当您将 USB 设备插入另一个端口时,没有实例 ID 的注册表项,从而触发驱动程序重新安装?
想象一下,两个相同的设备在两个不同的端口上被赋予相同的 ID;它们都使用相同的注册表项,如果设备具有相同的 PID 和 VID,这应该不是问题,因为它们不会有不同的驱动程序、设备类和功能。我猜它们可能会有,而且没有必要依赖这一点。最好每个设备都有自己的注册表项和 DIID(设备实例 ID),而不是共享它们。您可能希望根据设备逐个更改功能值。
组策略中有禁止某些 DIID 的设置,即禁止设备型号插入某些端口。如果设备在任何地方都有相同的 DIID,则您将禁止该型号插入所有端口。
另外,别忘了父母ID前缀。每个 USB 驱动器都有一个 ParentIDPrefix,用于标识 USBSTOR\ 子项,从而标识 MountedDevices 中的卷标,因为它位于值旁边的数据中。如果 2 个 USB 驱动器共享相同的注册表项,则会破坏任何依赖 ParentIDPrefix 值的软件。如果 Windows 没有为每个端口提供唯一的实例 ID,那么 2 个 USB 也将共享相同的 USBSTOR\ DIID,partmgr 几乎肯定会使用此项的名称作为卷的磁盘签名,并且将使用相同的磁盘 ID GUID 子项,这将为安装管理器创建未定义的情况,因为它不会看到具有相同签名的 2 个卷,但 1 个卷第二次请求卷号,但实际上是另一个卷,这可能会导致危险和未定义的行为。Windows 7 不支持 USB 驱动器上的多个卷,因此它使用 DIID,而不是 MBR 签名和偏移量。