conatainer_of () Makro im Linux Kernel -
Wenn Sie mehrere Datenstrukturen im Code verwalten möchten, müssen Sie fast immer eine Struktur in eine andere einbetten und jederzeit abrufen, ohne Fragen zu Speicherversätzen oder -grenzen zu erhalten. Angenommen, Sie haben eine Strukturperson, wie hier definiert:
struct person {
int age;
int salary;
char *name;
} p;
Wenn Sie nur einen Zeiger auf Alter oder Gehalt haben, können Sie die gesamte Struktur abrufen, die diesen Zeiger umschließt (enthält). Wie der Name schon sagt, wird das Makro container_of verwendet, um den Container des angegebenen Felds einer Struktur zu finden. Das Makro ist in include / linux / kernel.h definiert und sieht folgendermaßen aus:
#define container_of(ptr, type, member) ({ \
const typeof(((type *)0)->member) * __mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type, member)); })
Hab keine Angst vor den Zeigern; sehen Sie sie einfach wie folgt:
container_of(pointer, container_type, container_field);
Hier sind die Elemente des vorhergehenden Codefragments:
- Zeiger: Dies ist der Zeiger auf das Feld in der Struktur
- container_type: Dies ist die Art der Struktur, die den Zeiger umschließt (enthält)
- container_field: Dies ist der Name des Feldes, auf das der Zeiger innerhalb der Struktur zeigt
Betrachten wir den folgenden Container:
struct person {
int age;
int salary;
char *name;
};
Betrachten wir nun eine seiner Instanzen zusammen mit einem Zeiger auf das Altersmitglied:
struct person somebody;
[...]
int *age_ptr = &somebody.age;
Zusammen mit einem Zeiger auf das Namenselement (age_ptr) können Sie das Makro container_of verwenden, um einen Zeiger auf die gesamte Struktur (Container) zu erhalten, die dieses Element umschließt, indem Sie Folgendes verwenden:
struct person *the_person;
the_person = container_of(age_ptr, struct person, age);
container_of berücksichtigt den Versatz des Alters am Anfang der Struktur, um die richtige Zeigerposition zu erhalten. Wenn Sie den Versatz des Feldalters vom Zeiger age_ptr subtrahieren, erhalten Sie die richtige Position. Dies ist, was die letzte Zeile des Makros tut:
(type *)( (char *)__mptr - offsetof(type,member) );
Wenn Sie dies auf ein reales Beispiel anwenden, erhalten Sie Folgendes:
struct family {
struct person *father;
struct person *mother;
int number_of_sons;
int family_id;
} f;
[...]
int *fam_id_ptr = &f.family_id;
struct family *fam_ptr;
fam_ptr = container_of(fam_id_ptr, struct family, family_id);
Das Makro container_of wird hauptsächlich in generischen Containern im Kernel verwendet.
Das ist alles über container_of Makro im Kernel.
rb_node
.