使用时 lsusb
,我发现一个USB设备的总线号和设备号会时不时的发生变化。据我了解,总线编号可以在每次重新启动时更改。设备编号将在每次重新连接时更改。
我的问题是系统使用什么算法来获取总线号和设备号?尤其是设备号,是不是单调的?是否会出现在不重新启动操作系统的情况下,一个重新连接的设备正在使用另一个重新连接的设备的旧总线号和设备号的情况?
gro*_*mal 29
注意:这是一个Linux答案;其他内核会以稍微不同的方式来处理这个问题。
不谈 PCI 总线就很难谈 USB 总线。CPU 不能直接与 USB 总线通信,但发生的情况是 CPU 与连接有 USB 控制器的 PCI 总线通信(USB 控制器/集线器就是lsusb
所谓的 USB 总线)。PCI 总线根据它们与 CPU 的距离进行编号,例如:
+-----+
| CPU |
+-----+
| PCI Bus 0
---+--+-----------------------------+
| |
+---+----+ +----+---+
| Bridge | | Bridge |
+---+----+ +----+---+
| PCI bus 1 | PCI bus 2
--+--------+ +-------+-------------+
| | |
Disk Controller USB Controller Network Card
(Device 00) (Device 00) (Device 01)
Run Code Online (Sandbox Code Playgroud)
往里看,man lspci
我们看到以下内容:
Slot The name of the slot where the device resides
([domain:]bus:device.function). This tag is
always the first in a record.
Run Code Online (Sandbox Code Playgroud)
因此,我们现在知道如何解释 PCI 编号。接下来,我们将看看连接到 PCI 总线的 USB 控制器。我目前使用的机器有一个有趣的 USB 配置,所以我将使用它作为示例:
$ lspci -tv
-[0000:00]-+-00.0 Advanced Micro Devices, Inc. [AMD] RS780 Host Bridge
+-01.0-[01]----05.0 Advanced Micro Devices, Inc. [AMD/ATI] RS780M [Mobility Radeon HD 3200]
+-04.0-[02]----00.0 Qualcomm Atheros AR928X Wireless Network Adapter (PCI-Express)
+-05.0-[03]----00.0 Realtek Semiconductor Co., Ltd. RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller
+-06.0-[04-06]--
+-11.0 Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 SATA Controller [IDE mode]
+-12.0 Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 USB OHCI0 Controller
+-12.1 Advanced Micro Devices, Inc. [AMD/ATI] SB7x0 USB OHCI1 Controller
+-12.2 Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 USB EHCI Controller
+-13.0 Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 USB OHCI0 Controller
+-13.1 Advanced Micro Devices, Inc. [AMD/ATI] SB7x0 USB OHCI1 Controller
+-13.2 Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 USB EHCI Controller
+-14.0 Advanced Micro Devices, Inc. [AMD/ATI] SBx00 SMBus Controller
+-14.1 Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 IDE Controller
+-14.2 Advanced Micro Devices, Inc. [AMD/ATI] SBx00 Azalia (Intel HDA)
+-14.3 Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 LPC host controller
+-14.4-[07]--
+-14.5 Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 USB OHCI2 Controller
+-18.0 Advanced Micro Devices, Inc. [AMD] Family 11h Processor HyperTransport Configuration
+-18.1 Advanced Micro Devices, Inc. [AMD] Family 11h Processor Address Map
+-18.2 Advanced Micro Devices, Inc. [AMD] Family 11h Processor DRAM Controller
+-18.3 Advanced Micro Devices, Inc. [AMD] Family 11h Processor Miscellaneous Control
\-18.4 Advanced Micro Devices, Inc. [AMD] Family 11h Processor Link Control
Run Code Online (Sandbox Code Playgroud)
等等等等,这些优点是什么?在顶部,我们有域和 PCI 总线-[0000:00]
(这台机器只有一个 PCI 总线)。然后我们有几个设备连接到该总线。让我们看看哪些是 USB 设备:
$ lspci -tv | grep -i usb
+-12.0 Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 USB OHCI0 Controller
+-12.1 Advanced Micro Devices, Inc. [AMD/ATI] SB7x0 USB OHCI1 Controller
+-12.2 Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 USB EHCI Controller
+-13.0 Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 USB OHCI0 Controller
+-13.1 Advanced Micro Devices, Inc. [AMD/ATI] SB7x0 USB OHCI1 Controller
+-13.2 Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 USB EHCI Controller
+-14.5 Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 USB OHCI2 Controller
Run Code Online (Sandbox Code Playgroud)
好的,现在让我们将其与lsusb
(我使用sort
只是为了以后更容易搜索列表)进行比较:
$ lsusb | sort
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 002: ID 174f:5a31 Syntek Sonix USB 2.0 Camera
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 003 Device 002: ID 046d:c019 Logitech, Inc. Optical Tilt Wheel Mouse
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 006 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 007 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 007 Device 002: ID 0b05:1751 ASUSTek Computer, Inc. BT-253 Bluetooth Adapter
Run Code Online (Sandbox Code Playgroud)
再等等。我们有 7 个 USB 设备,lspci
但根据 10 个设备lsusb
! lspci
仅列出 USB 控制器;一个控制器可以连接多个 USB 设备。让我们探索一下/sys/bus/
,看看这是如何发生的。
$ ls -l /sys/bus/usb/devices/
... 1-0:1.0 -> ../../../devices/pci0000:00/0000:00:12.2/usb1/1-0:1.0
... 2-0:1.0 -> ../../../devices/pci0000:00/0000:00:13.2/usb2/2-0:1.0
... 2-1 -> ../../../devices/pci0000:00/0000:00:13.2/usb2/2-1
... 2-1:1.0 -> ../../../devices/pci0000:00/0000:00:13.2/usb2/2-1/2-1:1.0
... 2-1:1.1 -> ../../../devices/pci0000:00/0000:00:13.2/usb2/2-1/2-1:1.1
... 3-0:1.0 -> ../../../devices/pci0000:00/0000:00:12.0/usb3/3-0:1.0
... 3-1 -> ../../../devices/pci0000:00/0000:00:12.0/usb3/3-1
... 3-1:1.0 -> ../../../devices/pci0000:00/0000:00:12.0/usb3/3-1/3-1:1.0
... 4-0:1.0 -> ../../../devices/pci0000:00/0000:00:12.1/usb4/4-0:1.0
... 5-0:1.0 -> ../../../devices/pci0000:00/0000:00:13.0/usb5/5-0:1.0
... 6-0:1.0 -> ../../../devices/pci0000:00/0000:00:13.1/usb6/6-0:1.0
... 7-0:1.0 -> ../../../devices/pci0000:00/0000:00:14.5/usb7/7-0:1.0
... 7-1 -> ../../../devices/pci0000:00/0000:00:14.5/usb7/7-1
... 7-1:1.0 -> ../../../devices/pci0000:00/0000:00:14.5/usb7/7-1/7-1:1.0
... 7-1:1.1 -> ../../../devices/pci0000:00/0000:00:14.5/usb7/7-1/7-1:1.1
... 7-1:1.2 -> ../../../devices/pci0000:00/0000:00:14.5/usb7/7-1/7-1:1.2
... 7-1:1.3 -> ../../../devices/pci0000:00/0000:00:14.5/usb7/7-1/7-1:1.3
... usb1 -> ../../../devices/pci0000:00/0000:00:12.2/usb1
... usb2 -> ../../../devices/pci0000:00/0000:00:13.2/usb2
... usb3 -> ../../../devices/pci0000:00/0000:00:12.0/usb3
... usb4 -> ../../../devices/pci0000:00/0000:00:12.1/usb4
... usb5 -> ../../../devices/pci0000:00/0000:00:13.0/usb5
... usb6 -> ../../../devices/pci0000:00/0000:00:13.1/usb6
... usb7 -> ../../../devices/pci0000:00/0000:00:14.5/usb7
Run Code Online (Sandbox Code Playgroud)
现在,这开始变得有意义了:我们有 7 个 USB 控制器,它们作为设备插入 PCI 总线。例如,USB总线001对应PCI设备0000:00:12.2
,USB总线007对应0000:00:14.5
设备。
以 USB 总线编号(例如7-1:1.2
)开头的目录是连接到 USB 控制器的实际设备。就像 PCI 总线可以连接多个设备一样,USB 控制器(集线器)可以连接多个 USB 设备。
设备编号只是计数器:连接的第一个设备为 1,下一个为 2,依此类推。但还有一点:USB 设计为可热插拔;因此您可以连接和断开设备。当您断开 USB 设备的连接时,内核将不会再次将该设备编号用于该 USB 控制器上的任何其他设备。例如,如果您连接和断开笔式驱动器并继续操作,lsusb
您将看到笔式驱动器的设备编号上升。
如果您仔细阅读了以上内容,您可能会对我没有触及的一件事感到疑惑。PCI 编号的顺序与 USB 控制器的编号顺序不一致!让我们再看一遍:
USB | PCI
-----+----
usb1 | 0000:00/0000:00:12.2
usb2 | 0000:00/0000:00:13.2
usb3 | 0000:00/0000:00:12.0
usb4 | 0000:00/0000:00:12.1
usb5 | 0000:00/0000:00:13.0
usb6 | 0000:00/0000:00:13.1
usb7 | 0000:00/0000:00:14.5
Run Code Online (Sandbox Code Playgroud)
列表是有序的,但并不完全。前两个 USB 控制器似乎出现故障。然而,有一个原因:如果您仔细查看lspci
上面的输出,您会发现它们是EHCI
USB (USB 2.0),而所有其他 USB 控制器都是OHCI
USB (USB 1.x)。
因此,我们可以将该表重绘为:
USB | PCI
-----+----
usb1 | 0000:00/0000:00:12.2
usb2 | 0000:00/0000:00:13.2 USB 2.0
-----+---------------------------------
usb3 | 0000:00/0000:00:12.0 USB 1.x
usb4 | 0000:00/0000:00:12.1
usb5 | 0000:00/0000:00:13.0
usb6 | 0000:00/0000:00:13.1
usb7 | 0000:00/0000:00:14.5
Run Code Online (Sandbox Code Playgroud)
号码分配变得清晰!