Linuxカーネルのconatainer_of()マクロ-
コード内の複数のデータ構造を管理する場合、ほとんどの場合、メモリオフセットや境界について質問されることなく、ある構造を別の構造に埋め込み、いつでも取得する必要があります。ここで定義されているように、構造体の人がいるとしましょう。
struct person {
int age;
int salary;
char *name;
} p;
年齢または給与に関するポインターを設定するだけで、そのポインターをラップ(含む)構造全体を取得できます。名前が示すように、container_ofマクロは、構造体の特定のフィールドのコンテナーを見つけるために使用されます。マクロはinclude / linux / kernel.hで定義されており、次のようになります。
#define container_of(ptr, type, member) ({ \
const typeof(((type *)0)->member) * __mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type, member)); })
ポインタを恐れないでください。次のようにそれらを見てください:
container_of(pointer, container_type, container_field);
上記のコードフラグメントの要素は次のとおりです。
- ポインタ:これは構造体のフィールドへのポインタです
- container_type:これはポインターをラップする(含む)構造のタイプです
- container_field:これは、構造内でポインターが指すフィールドの名前です。
次のコンテナについて考えてみましょう。
struct person {
int age;
int salary;
char *name;
};
それでは、そのインスタンスの1つと、年齢メンバーへのポインターについて考えてみましょう。
struct person somebody;
[...]
int *age_ptr = &somebody.age;
名前メンバー(age_ptr)へのポインターとともに、container_ofマクロを使用して、以下を使用して、このメンバーをラップする構造全体(コンテナー)へのポインターを取得できます。
struct person *the_person;
the_person = container_of(age_ptr, struct person, age);
container_ofは、構造体の先頭の年齢のオフセットを考慮して、正しいポインター位置を取得します。ポインタage_ptrからフィールドageのオフセットを引くと、正しい場所が得られます。これは、マクロの最後の行が行うことです。
(type *)( (char *)__mptr - offsetof(type,member) );
これを実際の例に適用すると、次のようになります。
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);
container_ofマクロは、主にカーネルの汎用コンテナーで使用されます。
カーネルのcontainer_ofマクロについては以上です。
rb_node
。