1. ホーム
  2. c

[解決済み] Linuxカーネルにおけるcontainer_ofマクロの理解

2022-03-13 07:10:26

質問

Linuxカーネルをブラウズしていたら container_of マクロは次のように定義されています。

#define container_of(ptr, type, member) ({                      \
        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
        (type *)( (char *)__mptr - offsetof(type,member) );})

container_of が何をするのかは理解できたが、理解できないのは最後の文である。

(type *)( (char *)__mptr - offsetof(type,member) );})

次のようにマクロを使用すると

container_of(dev, struct wifi_device, dev);

最後の文の対応する部分は、次のようになります。

(struct wifi_device *)( (char *)__mptr - offset(struct wifi_device, dev);

というのは、何もしていないように見えます。 どなたかこの空白を埋めていただけませんか?

解決方法は?

使用例 container_of(dev, struct wifi_device, dev); は、2つの名前空間を混在させているため、少し誤解を招く可能性があります。

一方、最初の dev はポインタの名前を指しており、2番目の dev は構造体メンバの名前を指しています。

おそらく、このミックスアップが頭痛の種になっているのでしょう。実際 member パラメータは、コンテナ構造でそのメンバに付けられた名前を参照しています。

このコンテナを例にとると

struct container {
  int some_other_data;
  int this_data;
}

そしてポインタ int *my_ptr を追加しました。 this_data へのポインタを取得するためにマクロを使用します。 struct container *my_container を使うことで

struct container *my_container;
my_container = container_of(my_ptr, struct container, this_data);

のオフセットを取る。 this_data 構造体の先頭へのポインタを考慮することは、正しいポインタの位置を取得するために不可欠です。

実質的には、メンバである this_data ポインターから my_ptr をクリックすると、正しい位置が表示されます。

まさに、マクロの最終行がそうなっていますね。