Wie wurden USB-Busnummer und Gerätenummer vergeben?

19

Bei der Verwendung lsusbstelle ich fest, dass sich die Busnummer und die Gerätenummer eines USB-Geräts von Zeit zu Zeit ändern können. Soweit ich weiß, kann die Busnummer bei jedem Neustart geändert werden. Die Gerätenummer ändert sich bei jeder erneuten Verbindung.

Meine Frage ist, welchen Algorithmus das System verwendet, um die Busnummer und die Gerätenummer zu erhalten? Vor allem die Gerätenummer, ist es monoton? Wird es jemals den Fall geben, dass ein neu verbundenes Gerät ohne Neustart des Betriebssystems die alte Busnummer und Gerätenummer eines anderen neu verbundenen Geräts verwendet?

Conan
quelle
6
Eines hat mich neugierig gemacht, haben Sie wirklich gesehen, wie sich die BUS-Nummern nach einem Neustart geändert haben? Ich war immer zuversichtlich, dass sich die BUS-Nummern nicht ändern, wenn Sie nicht die Hardware ändern oder das BIOS aktualisieren. USB-Busse sind einfach Hubs / Controller, die an PCI-Busse angeschlossen sind (zumindest in allen Fällen, die ich gesehen habe), und die PCI-Bus-Informationen stammen aus dem BIOS. Aber ich könnte mich irren, ich will keine Antwort geben und Mist drin reden.
Grochmal
richtig, nur wenn ich hardwarewechsel habe sieht das so aus.
Conan

Antworten:

23

Hinweis: Dies ist eine Linux- Antwort. Andere Kernel werden etwas anders damit umgehen.

Kontext

Es ist schwierig, über USB-Busse zu sprechen, ohne über PCI-Busse zu sprechen. Eine CPU kann nicht mit einem USB-Bus kommunizieren. Dies geschieht, wenn die CPU mit einem PCI-Bus kommuniziert, an den ein USB-Controller angeschlossen ist (und ein USB-Controller / Hub lsusbeinen USB-Bus bezeichnet). PCI-Busse werden basierend auf dem Abstand zur CPU nummeriert. Beispiel:

    +-----+
    | CPU |
    +-----+
       |              PCI Bus 0
 ---+--+-----------------------------+
    |                                |
+---+----+                      +----+---+
| Bridge |                      | Bridge |
+---+----+                      +----+---+
    |  PCI bus 1                     |  PCI bus 2
  --+--------+               +-------+-------------+
             |               |                     |
       Disk Controller    USB Controller      Network Card
         (Device 00)       (Device 00)         (Device 01)

Wenn man lspciwir hineinschauen , sehen wir Folgendes:

   Slot   The  name of the slot where the device resides
          ([domain:]bus:device.function).  This tag is
          always the first in a record.

Deshalb wissen wir jetzt, wie man PCI-Nummern interpretiert. Als nächstes betrachten wir USB-Controller, die an die PCI-Busse angeschlossen sind. Die Maschine, an der ich mich gerade befinde, hat eine interessante USB-Konfiguration, die ich als Beispiel verwenden werde:

$ 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

Warte, warte, warte, was sind all diese Pluspunkte? Oben haben wir die Domäne und den PCI-Bus -[0000:00](dieser Rechner hat nur einen PCI-Bus). Und dann haben wir mehrere Geräte an diesen Bus angeschlossen. Mal sehen, welche USB-Geräte sind:

$ 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

Gut, jetzt vergleichen wir das mit lsusb(ich benutze es sortnur, um es später einfacher zu machen, die Liste zu durchsuchen):

$ 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

Warte nocheinmal. Wir haben 7 USB-Geräte nach, lspciaber 10 Geräte nach lsusb! lspcilistet nur die USB-Controller auf; An einen Controller können mehrere USB-Geräte angeschlossen sein. Lassen Sie uns untersuchen, /sys/bus/wie dies geschieht.

$ 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

Jetzt fängt das an Sinn zu machen, wir haben 7 USB-Controller, die als Geräte in den PCI-Bus eingesteckt sind. Beispielsweise entspricht der USB-Bus 001 dem PCI-Gerät 0000:00:12.2und der USB-Bus 007 dem 0000:00:14.5Gerät.

Gerätenummerierung

Die Verzeichnisse, die mit der USB-Busnummer beginnen (z. B. 7-1:1.2), sind die tatsächlichen Geräte, die an den USB-Controller angeschlossen sind. Genau wie an einen PCI-Bus mehrere Geräte angeschlossen sein können, können an einen USB-Controller (einen Hub) mehrere USB-Geräte angeschlossen sein.

Gerätenummern sind einfach Zähler: Das erste angeschlossene Gerät erhält eine 1, das nächste eine 2 und so weiter. Aber es gibt noch ein bisschen mehr: USB wurde als Hot-Plug-fähig konzipiert. Daher können Sie Geräte verbinden und trennen. Wenn Sie ein USB-Gerät trennen, wird die Gerätenummer vom Kernel nicht mehr für ein anderes Gerät auf diesem USB-Controller verwendet. Wenn Sie zum Beispiel ein USB-Stick anschließen und trennen und fortfahren, lsusbwird die Gerätenummer Ihres USB-Sticks angezeigt.

Busnummerierung

Wenn Sie die obigen Informationen aufmerksam gelesen haben, fragen Sie sich möglicherweise über eine Sache, die ich nicht angerührt habe. Die Reihenfolge der PCI-Nummerierung entspricht nicht der Reihenfolge, in der die USB-Controller nummeriert wurden! Lassen Sie uns das noch einmal sehen:

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

Die Liste ist in Ordnung, aber nicht ganz. Die ersten beiden USB-Controller scheinen nicht in Betrieb zu sein. Es gibt jedoch einen Grund dafür: Wenn Sie oben nachsehen, werden lspciSie feststellen, dass es sich um EHCIUSB (USB 2.0) handelt, während es sich bei allen anderen USB-Controllern um OHCIUSB (USB 1.x) handelt.

Daher können wir diese Tabelle neu zeichnen als:

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

Und die Nummernvergabe wird klar.

grochmal
quelle
Was passiert also, wenn die maximale Anzahl von Gerätenummern verwendet wird? Nehmen wir an, ich schließe mein Gerät weiter an. Die Gerätenummer wird demnächst auf die max. Ich habe tatsächlich einen Test gemacht, es sieht so aus, als wäre es kein einfacher Zähler. Es kehrt nicht zurück zu 001, sondern der Kernel verwendet die wenigen größten Gerätenummern erneut. Gibt es eine einfache Möglichkeit, dieses Verhalten zu ändern?
Conan
@Conan - Hmm ... nun, wie kann ich es sagen: Ich weiß es einfach nicht. Ich habe nie versucht, den Gerätezähler überzulaufen, wie Sie es getan haben. Andererseits ist es kaum erforderlich, eine Gerätenummer im Voraus zu kennen. Wenn Sie beispielsweise versuchen, ein USB-Laufwerk zu finden, während es angeschlossen wird, sollten Sie dies anhand der Dateisystembezeichnung oder der UUID tun (die sogar udevmehr oder weniger verstanden werden). Um die Nummerierung zum Zwecke des Lernens zu verstehen, glaube ich, dass der einzige Ort, an dem die Informationen vorliegen, der Kernel-Code ist.
Grochmal
Danke @grochmal, ich glaube ich habe Fehler beim Testüberlauf gemacht. Die späteren Tests haben mir beim Überlauf gezeigt, dass der Zähler tatsächlich von der niedrigeren Zahl sucht.
Conan