VorwortBei der Linux-Kernel-Programmierung werden Sie häufig auf eine Makrofunktion „container_of(ptr, type, member)“ stoßen. Beim Durchgehen des Quellcodes geraten normale Leute wie wir jedoch in Verzweiflung (was soll das alles? So können Funktionen definiert werden??? Warum steht da 0??? Ach, vergiss es, geben wir einfach auf …). Hier sind die Kernel-Meister so mächtig. Schon zwei Zeilen Code können uns an unserem Leben zweifeln lassen. Alles erfordert einen Prozess, also lass es langsam angehen. Tatsächlich ist das Prinzip sehr einfach: Suchen Sie bei gegebener Adresse ptr des Mitglieds des Strukturtyps die Startadresse des Strukturtyps. Die Startadresse vom Typ = ptr - Größe (hier muss sie in char* konvertiert werden, da sie in Bytes vorliegt). An dieser Stelle wurde die Funktion erklärt. Ist das nicht einfach? ? ? Eigentlich ist es das nicht. Es wird hier nicht erwähnt, wie die Größe berechnet wird, und das macht uns schwindelig. Beginnen wir mit dem Container des Funktionsprototyps: #define container_of(ptr, Typ, Mitglied) ({ \ const typeof( ((Typ *)0)->Mitglied ) *__mptr = (ptr); \ (Typ *)( (Zeichen *)__mptr - Offset von (Typ, Mitglied) );}) Als nächstes folgt der Prototyp der Funktion „offserof“: #define offsetof(TYP, MITGLIED) ((size_t) &((TYP *)0)->MITGLIED) Wie wäre es, ist es nicht cool? Okay, beginnen wir mit der Enthüllung: 1. Verwendung des 0-Zeigers (ich habe ihm meinen eigenen Namen gegeben, ich weiß nicht, ob es ein Problem gibt)Lassen wir die Fakten für sich sprechen: #include <stdio.h> Strukturtest { verkohle ich; int j; Zeichen k; }; int main() { Strukturtesttemperatur; printf("&temp = %p\n",&temp); printf("&temp.k = %p\n",&temp.k); printf("&((Strukturtest *)0)->k = %d\n",((int)&((Strukturtest *)0)->k)); } Nach dem Kompilieren und Ausführen erhalten Sie möglicherweise die folgenden Ergebnisse:
Sie verstehen, was ich meine: Die benutzerdefinierte Struktur hat drei Variablen: i, j und k. Aufgrund der Anforderung der Byte-Ausrichtung beträgt die Größe der Struktur 4 Bytes * 3 = 12 Bytes. Die Funktion von &((struct test *)0)->k besteht darin, die Anzahl der Bytes von k bis zur Startadresse der Strukturtemp (also unsere Größe) zu ermitteln. Hier wird 0 zwangsweise in den Typ „struct test *“ konvertiert, und seine Rolle besteht darin, als Zeiger auf die Startadresse der Struktur zu dienen, und die Rolle von & ((struct test *) 0) -> k besteht darin, die Anzahl der Bytes von k bis zum Startzeiger zu berechnen. . . Tatsächlich geht es darum, die relative Adresse zu finden. Die Startadresse ist 0, also ist der Wert von &k die Größe (Hinweis: Da beim Drucken eine Ganzzahl erforderlich ist, erfolgt eine erzwungene Konvertierung in int), sodass wir die benötigte Größe finden können. Nun, ich habe versehentlich die Funktionalität der Funktion offsetof() fertig erklärt: #define offsetof(TYP, MITGLIED) ((size_t) &((TYP *)0)->MITGLIED) Diesmal sieht es besser aus, oder? (Ich verstehe immer noch nicht, warum es auf der untersten Ebene so ist ... ich weiß nur, dass es so funktioniert), also besteht die Funktion von offsetof() darin, die Größe zu finden, von der wir träumen, und sie in der Form size_t (size_t: vorzeichenlose Ganzzahl) zurückzugeben. 2. Strenge der Kernel-Programmierung#define container_of(ptr, Typ, Mitglied) ({ \ const typeof( ((Typ *)0)->Mitglied ) *__mptr = (ptr); \ (Typ *)( (Zeichen *)__mptr - Offset von (Typ, Mitglied) );}) Hier betrachten wir nur die zweite Zeile: const typeof( ((Typ *)0)->Mitglied ) *__mptr = (ptr); Was ist seine Funktion? Eigentlich hat es keine große Wirkung (bitte kritisieren Sie mich nicht, lassen Sie mich ausreden), aber der Form nach ist _mptr = ptr, warum müssen wir also dieselbe Variable definieren? ? ? Tatsächlich ist dies die Genialität der Kernel-Entwickler: Wenn bei der Verwendung ein Problem mit den vom Entwickler eingegebenen Parametern auftritt (ptr und Mitgliedstypen stimmen nicht überein), wird während der Kompilierung eine Warnung angezeigt. Wenn jedoch der Zeilenumbruch entfernt wird, wird keine Warnung angezeigt, und diese Warnung ist genau erforderlich (um Fehler zu vermeiden, ohne zu wissen, wo der Fehler liegt). . . Das ist streng, oder? Typ von ((Typ *)0)->Mitglied) Seine Funktion besteht nur darin, den Mitgliedstyp zu ermitteln. Mehr nicht. Dies ist im Grunde das Ende 3. FazitDie Implementierung der Funktion container_of(ptr, type, member) besteht aus zwei Teilen: 1. Bestimmen Sie, ob ptr und Mitglied vom gleichen Typ sind 2. Berechnen Sie die Größe, die Startadresse der Struktur = (Typ *) ((char *) ptr - Größe) (Hinweis: Erzwungene Konvertierung in den Strukturzeiger). Jetzt wissen wir, dass die Funktion von container_of() darin besteht, die erste Adresse einer Strukturvariablen über die Adresse eines Mitglieds in der Strukturvariablen zu finden. container_of(ptr,Typ,Mitglied), wobei ptr, Typ und Mitglied jeweils Zeiger, Typ und Mitglied darstellen. Dies ist das Ende dieses Artikels über die of()-Funktion des Linux-Kernel-Programmiercontainers. Weitere verwandte Inhalte zur of()-Funktion des Linux-Containers finden Sie in den vorherigen Artikeln von 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, dass jeder 123WORDPRESS.COM in Zukunft unterstützen wird! Das könnte Sie auch interessieren:
|
<<: Optimale Webseitenbreite und ihre kompatible Implementierungsmethode
>>: 2 Gründe, warum die HTML-CSS-Tag-Stileinstellung nicht funktioniert
1. Problembeschreibung Aus bestimmten Gründen ist...
In diesem Artikelbeispiel wird der spezifische Co...
Seit Zabbix Version 3.0 wird verschlüsselte Kommu...
Die einfachste Store-Anwendung in Vue ist die glo...
html Code kopieren Der Code lautet wie folgt: <...
1. InnoDB-Sperrmechanismus Die InnoDB-Speicher-En...
Inhaltsverzeichnis Projekthintergrund Verbesserun...
Für die Entwicklung benötigen Sie immer Daten. Al...
Zu den vom HTTP/1.1-Protokoll angegebenen HTTP-An...
Inhaltsverzeichnis 502 Bad Gateway Fehlerbildung ...
Die Methoden und Konzepte privater und globaler F...
Inhaltsverzeichnis 1. Was ist SVN? 2. Methoden zu...
Inhaltsverzeichnis MAH 1. Einführung in die MAH-A...
Ich hoffe, einige Eigenschaften des Abfrageformul...
Frage: Die Kodierung meines Blogs ist UTF-8. Manch...