makro conatainer_of () w jądrze Linuksa -
Jeśli chodzi o zarządzanie kilkoma strukturami danych w kodzie, prawie zawsze będziesz musiał osadzić jedną strukturę w innej i odzyskać je w dowolnym momencie bez zadawania pytań o przesunięcia lub granice pamięci. Powiedzmy, że masz osobę struct, jak zdefiniowano tutaj:
struct person {
int age;
int salary;
char *name;
} p;
Mając tylko wskaźnik na wiek lub wynagrodzenie, możesz pobrać całą strukturę opakowującą (zawierającą) ten wskaźnik. Jak sama nazwa wskazuje, makro container_of służy do wyszukiwania kontenera danego pola struktury. Makro jest zdefiniowane w include / linux / kernel.h i wygląda następująco:
#define container_of(ptr, type, member) ({ \
const typeof(((type *)0)->member) * __mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type, member)); })
Nie bój się wskazówek; po prostu zobacz je w następujący sposób:
container_of(pointer, container_type, container_field);
Oto elementy poprzedniego fragmentu kodu:
- pointer: To jest wskaźnik do pola w strukturze
- typ_kontenera: jest to typ zawijania struktury (zawierającej) wskaźnik
- container_field: jest to nazwa pola, na które wskaźnik wskazuje wewnątrz struktury
Rozważmy następujący kontener:
struct person {
int age;
int salary;
char *name;
};
Rozważmy teraz jedno z jego wystąpień, wraz ze wskaźnikiem do członka wieku:
struct person somebody;
[...]
int *age_ptr = &somebody.age;
Wraz ze wskaźnikiem do elementu członkowskiego imienia (age_ptr) możesz użyć makra container_of, aby uzyskać wskaźnik do całej struktury (kontenera), który otacza ten element członkowski, używając następującego polecenia:
struct person *the_person;
the_person = container_of(age_ptr, struct person, age);
container_of bierze pod uwagę przesunięcie wieku na początku struktury, aby uzyskać poprawną lokalizację wskaźnika. Jeśli odejmiesz przesunięcie wieku pola od wskaźnika age_ptr, otrzymasz poprawną lokalizację. Oto, co robi ostatnia linia makra:
(type *)( (char *)__mptr - offsetof(type,member) );
Odnosząc to do prawdziwego przykładu, daje to:
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);
Makro container_of jest używane głównie w ogólnych kontenerach jądra.
To wszystko o makrze container_of w jądrze.
rb_node
.