Haben Sie beim Erlernen des Linux-Betriebssystems schon einmal die Frage: Warum können unsere Computer verschiedene USB-Geräte erkennen und verwenden? Warum verwendet das Linux-System die Maus nicht als Tastatur? Lassen Sie uns den Identifizierungs- und Ladevorgang von USB-Geräten in Linux-Systemen besprechen.
Wenn wir ein USB-Gerät an den Computer anschließen, erkennt und lädt der Linux-Kernel automatisch den entsprechenden Treiber, damit das Gerät ordnungsgemäß funktionieren kann. Als nächstes werden wir uns mit dem Identifizierungs- und Ladevorgang von USB-Geräten in Linux-Systemen befassen.
Ein USB-Controller ist ein Hardwaregerät, das zur Steuerung von Geräten am USB-Bus verwendet wird. Wenn Sie ein USB-Gerät anschließen, erkennt der USB-Controller die Spannungsänderung und sendet ein Unterbrechungssignal. Dieses Interrupt-Signal wird an die Interrupt-Leitung des USB-Controllers am Prozessor gesendet und teilt dem Linux-Kernel mit, dass ein neues USB-Gerät angeschlossen ist.
Wenn der Kernel das Interrupt-Signal vom USB-Controller empfängt, ruft er das usbcore
模块,该模块负责检测新的USB设备并加载相应的驱动程序。usbcore
-Modul im USB-Subsystem auf, um zunächst den Gerätedeskriptor zu erkennen. Dieser Deskriptor enthält die Hersteller-ID, die Produkt-ID, den Kategoriecode und andere Informationen.
Wenn bereits ein passender Treiber vorhanden ist, lädt das usbcore
Modul diesen Treiber. Wenn kein passender Treiber vorhanden ist, wird versucht, einen universellen Treiber zu laden, der die meisten USB-Geräte unterstützt.
Sobald der richtige Treiber geladen ist, registriert er sich beim USB-Subsystem und teilt ihm mit, welche Geräte er verarbeiten kann. Dieser Schritt umfasst normalerweise die Registrierung der Klasse des USB-Geräts (z. B. Speichergerät, Eingabegerät usw.) beim Kernel.
Dieser Vorgang umfasst die Registrierung eines neuen USB-Gerätetreibers beim Kernel und die Angabe der Hersteller-ID, Produkt-ID und anderer Informationen des Geräts im Treiber. Sobald der Treiber erfolgreich registriert wurde, kann das USB-Subsystem dem Gerät den richtigen Treiber zuordnen.
Das USB-Subsystem erstellt als Nächstes einen Geräteknoten für das Gerät. Ein Geräteknoten ist eine spezielle Datei im /dev
-Verzeichnis, die es User-Space-Programmen ermöglicht, mit dem Gerät zu kommunizieren. Der Name des Geräteknotens wird normalerweise dynamisch vom Kernel basierend auf der Hersteller-ID, Produkt-ID, Seriennummer und anderen Informationen des Geräts generiert.
Die Erstellung von Geräteknoten wird durch den udev
Daemon-Prozess erreicht, der Ereignisse beim Ein- und Ausstecken von Geräten im System überwacht und automatisch entsprechende Geräteknoten erstellt oder löscht. Sobald der Geräteknoten erstellt ist, kann der Kernel User-Space-Programmen Zugriffsrechte auf das Gerät zuweisen.
Nachdem der Treiber benachrichtigt wurde, dass ein neues Gerät angeschlossen ist, initialisiert er das Gerät. Die Initialisierung kann das Festlegen der Übertragungsrate des Geräts, das Zuweisen von Speicherpuffern usw. umfassen. Nachdem die Geräteinitialisierung abgeschlossen ist, meldet der Treiber dem USB-Subsystem, dass das Gerät bereit ist.
Endlich können User-Space-Programme Geräteknoten öffnen und mit dem Gerät kommunizieren. Die Berechtigungen von Geräteknoten sind normalerweise so eingestellt, dass sie nur dem Root-Benutzer oder Benutzern in relevanten Gruppen Zugriff gewähren. Benutzerraumprogramme können Systemaufrufe (z. B. read
和write
) verwenden, um Befehle an das Gerät zu senden und Daten zu empfangen.
Durch diesen Vorgang kann das Linux-System das Gerät automatisch identifizieren und den entsprechenden Treiber laden, damit das Gerät normal funktionieren kann. Aus diesem Grund müssen wir beim Anschließen eines USB-Geräts keine Treiber manuell installieren oder andere Vorgänge ausführen, um das Gerät direkt verwenden zu können.
Wenn Sie ein USB-Gerät anschließen, führt das Linux-System automatisch die oben genannten Schritte aus, um das Gerät automatisch zu identifizieren und den entsprechenden Treiber zu laden, damit das Gerät normal funktionieren kann. Lassen Sie uns den Prozess auf Codeebene analysieren.
Im Folgenden erkläre ich den Identifizierungs- und Ladevorgang von USB-Geräten im Linux-System anhand einiger Beispielcodes. Diese Beispielcodes dienen lediglich der Erläuterung der Prinzipien, der eigentliche Code wird komplexer sein.
Wenn ein USB-Gerät an das System angeschlossen wird, wird ein Interrupt-Signal erzeugt, das von der USB-Controller-Interrupt-Leitung am Prozessor erfasst und vom USB-Subsystem des Kernels verarbeitet wird. Hier ist ein Beispielcode, der zeigt, wie Ereignisse beim Ein- und Ausstecken von USB-Geräten erkannt werden:
#include #include int main() { libusb_device **devs; libusb_context *ctx = NULL; int r = libusb_init(&ctx); if (r printf("Failed to initialize libusb\n"); return 1; } // 扫描USB总线并列出所有连接的设备 ssize_t cnt = libusb_get_device_list(ctx, &devs); if (cnt printf("Failed to get device list\n"); return 1; } // 遍历设备列表,检测插入和拔出事件 for (int i = 0; i if (r printf("Failed to get device descriptor\n"); continue; } printf("Vendor ID: 0x%04x, Product ID: 0x%04x\n", desc.idVendor, desc.idProduct); } // 释放设备列表 libusb_free_device_list(devs, 1); // 退出libusb libusb_exit(ctx); return 0; }
Dieser Code verwendet die libusb-Bibliothek, eine C-Sprachbibliothek, die für den Zugriff auf USB-Geräte verwendet wird. Es bietet eine API zum Initialisieren des USB-Subsystems und zum Scannen des USB-Busses sowie eine API für den Zugriff auf USB-Geräte.
Sobald ein Gerät als angeschlossen erkannt wird, versucht das USB-Subsystem, einen geeigneten Treiber zu laden. Nachfolgend finden Sie einen Beispieltreibercode, der für die Unterstützung von USB-Speichergeräten (z. B. USB-Flash-Laufwerken) verantwortlich ist:
#include #include static struct usb_device_id storage_devices[] = { { USB_DEVICE(0xabcd, 0x1234) }, { USB_DEVICE(0xffff, 0xffff) }, { } }; MODULE_DEVICE_TABLE(usb, storage_devices); static int storage_probe(struct usb_interface *interface, const struct usb_device_id *id) { // 初始化设备并注册 return 0; } static void storage_disconnect(struct usb_interface *interface) { // 释放设备 } static struct usb_driver storage_driver = { .name = "usb-storage", .probe = storage_probe, .disconnect = storage_disconnect, .id_table = storage_devices, }; module_usb_driver(storage_driver);
Dieser Code demonstriert einen einfachen Treiber, der Plug-in- und Unplug-Ereignisse für USB-Speichergeräte verarbeiten kann. Beim Laden eines Treibers durchsucht der Kernel die Liste der geladenen Treiber nach einem Treiber, der zum Gerät passt.
Wenn ein passender Treiber gefunden wird, verwendet der Kernel diesen Treiber zur Verwaltung des Geräts. Wenn kein passender Treiber gefunden wird, lädt der Kernel keinen Treiber.
Sobald ein zum Gerät passender Treiber gefunden wird, wird der Treiber geladen und gestartet. Er versucht, das Gerät zu initialisieren und beim Kernel zu registrieren. Hier ist ein Beispielcode, der zeigt, wie man ein USB-Speichergerät initialisiert und beim Kernel registriert:
static int storage_probe(struct usb_interface *interface, const struct usb_device_id *id) { struct usb_device *dev = interface_to_usbdev(interface); // 获取设备描述符 struct usb_device_descriptor desc; int r = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &desc, sizeof(desc)); if (r "Failed to get device descriptor\n"); return r; } // 打印设备信息 printk(KERN_INFO "USB storage device detected: Vendor ID=0x%04x, Product ID=0x%04x\n", desc.idVendor, desc.idProduct); // 初始化设备并注册到内核 // ... return 0; }
Der obige Beispielcode verwendet die usb_get_descriptor()
函数来获取设备描述符,并使用printk()
-Funktion des Kernels, um Geräteinformationen im Kernel-Protokoll aufzuzeichnen.
Der Treiber ruft die Geräteinitialisierungsfunktion auf und registriert sie beim Kernel. Da der Prozess der Geräteinitialisierung und -registrierung jedoch von Gerät zu Gerät unterschiedlich ist, wird dieser Teil des Codes hier weggelassen.
一旦设备已经被注册到内核,用户空间程序就可以通过设备节点来访问设备。在Linux系统中,设备节点是一种特殊的文件,可以通过标准文件I/O函数来访问。下面是一个示例代码,演示如何打开并读取USB存储设备:
#include #include #include int main() { // 打开设备节点 int fd = open("/dev/sdb", O_RDONLY); if (fd printf("Failed to open device\n"); return 1; } // 读取设备数据 char buf[1024]; ssize_t n = read(fd, buf, sizeof(buf)); if (n printf("Failed to read device\n"); close(fd); return 1; } // 关闭设备节点 close(fd); return 0; }
这段代码使用了标准的文件I/O函数来访问设备节点。在这个例子中,设备节点的路径是/dev/sdb
,这是一个典型的USB存储设备节点。接下来,程序将设备节点作为文件打开,并使用read()
函数从设备中读取数据。一旦完成数据的读取,程序将关闭设备节点并退出。
Linux系统识别USB设备的过程可以分为四个步骤:设备连接、驱动匹配、设备注册和设备访问。当用户将USB设备插入计算机时,内核将通过USB总线来检测设备的插入事件,并尝试查找与设备匹配的驱动程序。一旦找到了匹配的驱动程序,驱动程序将被加载并启动,它将尝试对设备进行初始化,并将其注册到内核。一旦设备已经被注册到内核,用户空间程序就可以通过设备节点来访问设备。
在Linux系统中,驱动程序是非常重要的组成部分,它们负责管理和控制系统中的各种设备。对于USB设备而言,内核提供了一个通用的USB驱动框架,它可以自动检测和加载驱动程序,并为用户提供了一个简单而强大的USB设备访问接口。通过深入理解USB驱动程序的工作原理,我们可以更好地理解Linux系统中设备管理的内部机制,这对于开发和调试设备驱动程序非常有帮助。
Das obige ist der detaillierte Inhalt vonWie erkennt Linux das USB-Gerät, das ich angeschlossen habe?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!