VorwortVor kurzem musste ich in einem Projekt das LED-Subsystem verwenden. In Embedded Linux ist es relativ einfach, ein Licht einzuschalten. Sie müssen nur einen bestimmten Wert in die entsprechende Datei im Verzeichnis schreiben, das einem bestimmten Licht entspricht, und schon können Sie die LED ein-/ausschalten/blinken lassen. # echo 1 > /sys/class/leds/green/brightness // Schalte die LED ein # echo 0 > /sys/class/leds/green/brightness // Schalte die LED aus # echo heartbeat > /sys/class/leds/green/trigger // Lasse die LED wie einen Herzschlag blinken LED-TriggerNatürlich ist die im Projekt verwendete Beleuchtungsfunktion etwas komplizierter als die oben vorgestellte. Sie ähnelt der Festplattenbeleuchtung, d. h. die LED blinkt, wenn von der Festplatte gelesen oder geschrieben wird. Ich habe das vage Gefühl, dass diese Funktion mit der Triggerdatei zusammenhängen sollte, denn wenn ich diese Datei cate, ist das Wort mmc0 darin enthalten. Schreiben Sie dann mmc0 in den Trigger und sehen Sie, welche Wirkung es hat. # echo mmc0 > /sys/klasse/leds/grün/trigger # Katze /sys/Klasse/LEDs/grün/Trigger keine rc-feedback kbd-scrolllock kbd-numlock kbd-capslock kbd-kanalock kbd-Umschalttaste kbd-Alt-Taste kbd-Strg-Taste kbd-Alt-Taste kbd-Umschalttaste kbd-Umschaltsperre kbd-Strg-Sperre kbd-Strg-Sperre [mmc0] Heartbeat standardmäßig eingeschaltet, IR-Power-Click axp20x-usb-online Schreiben von Daten auf die Festplatte # aa berühren | synchronisieren Wie durch Zauberei stellte ich fest, dass jedes Mal, wenn ein Befehl zum Schreiben von Daten auf die Festplatte ausgeführt wurde, das grüne Licht auf der Platine einmal aufblinkte. Durch Nachschlagen in den Informationen habe ich erfahren, dass es sich hierbei um eine Funktion handelt, die mit dem LED-Trigger zusammenhängt. Einen Moment lang dachte ich
Mir kamen alle möglichen Zweifel und ich wollte unbedingt die Prinzipien hinter diesen Funktionen verstehen. Entdecken SieProbleme führen zum Handeln. Listen Sie die Fragen auf, die Sie zuerst beantworten möchten. Woher stammen die Verzeichnisse zu den einzelnen Leuchten?
Beginnen wir mit der Recherche und starten mit dem, was mir letzte Nacht eingefallen ist: led_classdev_register("aaa") generiert ein LED-Verzeichnis. LED-GeräteregistrierungLassen Sie uns ein Experiment durchführen, um festzustellen, ob led_classdev_register() ein Verzeichnis generiert, das dem LED-Licht entspricht. Ich habe zufällig einen Ort gefunden, an dem ich die folgenden Codezeilen ausführen kann, und sie hinzugefügt, in der Hoffnung, dass das Verzeichnis aaa im Verzeichnis leds generiert werden kann Struktur led_classdev *cdev; int ret; cdev = kzalloc(Größe von(*cdev), GFP_KERNEL); wenn (!cdev) Rückgabe -ENOMEM; cdev->name = "aaa"; // cdev->brightness_set = ebsa110_led_set; // cdev->brightness_get = ebsa110_led_get; // cdev->default_trigger = "Herzschlag"; ret = led_classdev_register(NULL, cdev); wenn (ret < 0) { kfree(cdev); Rückkehr ret; } Kompilieren, brennen, ausführen, anzeigen
Und tatsächlich wurde das Verzeichnis „aaa“, das ich erwartet hatte, unter „leds“ generiert, und mein Selbstvertrauen wuchs enorm! Später habe ich die zugrunde liegende Anrufbeziehung nachverfolgt: led_classdev_register() of_led_classdev_register() // registriere ein neues Objekt der Klasse led_classdev. led_classdev_next_name() Gerät_erstellen_mit_Gruppen() led_add_brightness_hw_changed() list_add_tail() // zur Liste der LEDs hinzufügen led_update_helligkeit() //led_trigger_set_default() LED-VerzeichnisNachdem ich nun weiß, wie ein bestimmtes Licht registriert wird, möchte ich wissen, wie das LED-Verzeichnis generiert wird. Ich habe den Code durchsucht und es ist nicht schwer, ihn zu finden. Im Folgenden ist die Funktionsaufrufbeziehung im Zusammenhang mit der Generierung des LED-Verzeichnisses aufgeführt: subsys_initcall(leds_init); leds_init() // Erstelle die LED-Klasse, d.h. erzeuge das Verzeichnis /sys/class/leds class_create() __Klasse_erstellen() __class_register() kset_register() durch Analogie verstehenSpäter überprüfte ich die Informationen und stellte fest, dass /sys/class/leds eine Klasse ist. Eine Klasse stellt ein Kernel-Subsystem dar. Im Kernel gibt es viele solcher Subsysteme. Jedes Verzeichnis in /sys/class/ ist eine Klasse und auch ein Subsystem. # ls /sys/Klasse/ ata_device extcon mdio_bus ptp Ton ata_link gpio Speicher pwm spi_master ata_port Grafik Sonstiges RC Wärmebild bdi hwmon mmc_host Regler tty Block I2C-Adapter Netz RTC UDC bsg i2c-dev phy scsi_device vc DMA-Eingang Stromversorgung SCSI-Disk VT-Konsole DRM LEDs PPS SCSI_Host Watchdog Jede Klasse hat spezifische Instanziierungsobjekte, wie grün, aaa
Jedes Objekt hat entsprechende Mitgliedsmethoden/Attribute, wie Helligkeit, Trigger # ls /sys/klasse/leds/aaa/ Helligkeits-/Einschalttrigger max_brightness-Subsystem uevent Es ist so ähnlich wie eine Klasse in C++! Tatsächlich ist es eine Klasse, ein einfacher Vergleich Ich werde die Registrierungslogik im jeweiligen Kurs langsam studieren, wenn ich später Zeit habe. Setzen Sie unsere Routenerkundung fort. Beachten Sie, dass sich meine Erkundungsroute hier geändert hat. Sie ist nicht mehr auf die Erkundung des LED-Subsystems beschränkt, sondern hat begonnen, sich auf den Kernel außerhalb des LED-Subsystems auszudehnen. Generierung eines KlassenverzeichnissesKommen wir nun zum Klassenverzeichnis. Nachdem wir nun wissen, woher das Verzeichnis „LEDs“ stammt, fragen wir uns, woher das darüber liegende Klassenverzeichnis stammt. Folgen Sie dem Code und erhalten Sie Klassen_init () kset_create_and_add("class", NULL, NULL); // Erstelle dynamisch eine Struktur kset und füge sie zu sysfs hinzu kset_create() kobject_set_name() kset_register() kset_init() kobject_add_internal() kobject_get() kobj_kset_join() kset_get() list_add_tail() __list_add() { nächstes->vorheriges = neu; neu->nächstes = nächstes; neu->vorherige = vorige; } create_dir() // Erstelle ein Verzeichnis start_kernel()Tatsächlich muss ich nach der Verfolgung bis classes_init() nicht darüber nachdenken, welchen Code ich weiter unten verfolgen soll, sondern kann einfach weiter nach oben verfolgen. /* Kernel */ start_kernel() rest_init() // Mach den Rest non-__init'ed, wir sind jetzt am Leben kernel_thread(kernel_init, NULL, CLONE_FS); kernel_init() kernel_init_freeable() /* * Ok, die Maschine ist nun initialisiert. Keines der Geräte * wurden noch nicht berührt, aber das CPU-Subsystem ist aktiv und * läuft, und die Speicher- und Prozessverwaltung funktioniert. * * Jetzt können wir endlich mit der richtigen Arbeit beginnen. */ führe_grundlegendes_Setup durch () driver_init() // um ihre Subsysteme zu initialisieren. devtmpfs_init() Geräte_init() Busse_init() classes_init() // nur classes_init() firmware_init() hypervisor_init() Plattformbusinit () cpu_dev_init() Speicher_dev_init() container_dev_init() von_core_init() Wie oben erwähnt, habe ich zufällig start_kernel() gefunden, wo der Traum begann. Es war das erste Mal, dass ich das Verfolgen von Kernelcode so interessant fand. Kernel wird gestartet …Nachdem ich zu start_kernel() zurückgefunden hatte, fragte ich mich unwillkürlich, wo dieser String „Starting kernel ...“ gedruckt wurde. Ich kann diesen Satz jedes Mal sehen, wenn ich uboot starte. Wäre es nicht toll, wenn ich ihn finden könnte? Leider konnte ich es im Kernelcode nicht finden. ubootZuerst dachte ich, dass „Starting kernel ...“ in start_kernel() gedruckt würde, aber ich konnte es im Kernelcode nicht finden. Zu diesem Zeitpunkt habe ich mich gefragt, ob es in ubbot gedruckt wurde. Es ist sinnvoll, diesen Satz auszudrucken, bevor mit dem Laden des Kernels begonnen wird. Ich habe in uboot gesucht und gefunden boot_jump_linux() ankündigen und aufräumen() printf("\nKernel wird gestartet ...%s\n", fake ? "(Fake-Lauf zur Ablaufverfolgung)" : ""); Hier wird uboot beendet und der Kernel ausgeführt. Anbei die komplette AnrufbeziehungVon Uboot zum Kernel und dann zu /sys/class, dann die LED-Klasse registrieren und eine Instanziierung eines LED-Lichts durchführen. /* uboot */ boot_jump_linux() ankündigen und aufräumen() printf("\nKernel wird gestartet ...%s\n"); // printf() Bootstage_Mark_Name(BOOTSTAGE_ID_BOOTM_HANDOFF, "Start_Kernel"); bereinigen_vor_linux() kernel_entry(0, machid, r2); /* Kernel */ start_kernel() rest_init() // Mach den Rest non-__init'ed, wir sind jetzt am Leben kernel_thread(kernel_init, NULL, CLONE_FS); kernel_init() kernel_init_freeable() /* * Ok, die Maschine ist nun initialisiert. Keines der Geräte * wurden noch nicht berührt, aber das CPU-Subsystem ist aktiv und * läuft, und die Speicher- und Prozessverwaltung funktioniert. * * Jetzt können wir endlich mit der richtigen Arbeit beginnen. */ führe_grundlegendes_Setup durch () driver_init() // um ihre Subsysteme zu initialisieren. devtmpfs_init() Geräte_init() Busse_init() Klassen_init () kset_create_and_add("class", NULL, NULL); // Erstelle dynamisch eine Struktur kset und füge sie zu sysfs hinzu kset_create() kobject_set_name() kset_register() kset_init() kobject_add_internal() kobject_get() kobj_kset_join() kset_get() list_add_tail() __list_add() { nächstes->vorheriges = neu; neu->nächstes = nächstes; neu->vorherige = vorige; } create_dir() firmware_init() hypervisor_init() Plattformbusinit () cpu_dev_init() Speicher_dev_init() container_dev_init() von_core_init() subsys_initcall(leds_init); leds_init() // Erstelle die LED-Klasse, also das Verzeichnis /sys/class/leds class_create() __Klasse_erstellen() __class_register() kset_register() led_classdev_register() of_led_classdev_register() // registriere ein neues Objekt der Klasse led_classdev. led_classdev_next_name() Gerät_erstellen_mit_Gruppen() led_add_brightness_hw_changed() list_add_tail() // zur Liste der LEDs hinzufügen led_update_helligkeit() //led_trigger_set_default() Eintrittspunkt ins LebenDas Obige ist eine Studie des Linux-Kernels aus der Perspektive des LED-Subsystems. Einstiegspunkt zum Studium des Linux-Kernels gefunden. Wenn wir mit großen Dingen konfrontiert werden, empfinden wir oft Angst. Diese Angst hält uns davon ab, tiefer zu forschen, was dazu führt, dass wir sie nicht verstehen und nicht in der Lage sind, sie zu bewältigen. Zwei Beispiele:
Von etwas so Kleinem wie einer Frage, einem Thema oder einer Fähigkeit bis hin zu etwas so Großem wie der Arbeit, dem Leben oder sogar dem ganzen Leben. Wenn wir einen Einstiegspunkt finden, haben wir Glück und können ihn nutzen, um erfolgreich zu sein und eine bessere Zukunft zu erreichen. Ich hoffe, dass jeder 123WORDPRESS.COM in Zukunft unterstützen wird! Das könnte Sie auch interessieren:
|
>>: Stellen Sie die Breite der Tabelle so ein, dass sie sich nicht mit dem Text ändert
Verwenden Sie den Befehl „Find“, um Dateien zu fi...
Inhaltsverzeichnis Redis auf Docker installieren ...
Überblick Das Builder-Muster ist ein relativ einf...
1. Allgemeine MySQL-Konfiguration Alle folgenden ...
Inhaltsverzeichnis 1. Automatische Installation m...
Mobile Browser platzieren Webseiten in einem virtu...
Das Installationstutorial für MySQL 8.0.11 WinX64...
Das Transaktionsprotokoll zeichnet die Vorgänge a...
Inhaltsverzeichnis 1. Neu II. Änderung element-ui...
1. Importieren Sie das Modul und definieren Sie e...
Vor Kurzem habe ich gelernt, mit Nginx statische ...
Für dieses Beispiel ist das Herunterladen und Ins...
1. Konzept 1. Der Unterschied zwischen Hot Backup...
In diesem Artikel wird der spezifische Code von v...
Inhaltsverzeichnis Vorwort Nr.1 Ein Fokus Nr. 2 E...