user/include/linux/list.h
この宣言:
#define list_entry(ptr, type, member) \
((type *)((char *)(ptr) – (unsigned long)(&((type *)0)->member)))
誰かがこれが何であるか、そしてそれがどのように機能するかを説明できますか、事前に感謝します
P.S.できるだけ答えを単純化してください。Linuxのスレッドやプロセスについて知っています。現在、可能性を模索していますが、これに少しこだわっています。
次のような2つの構造体について考えてみます。
_struct data {
int something;
};
struct container {
int something_before;
struct data data_item;
int something_after;
};
_
_struct data
_値へのポインターがあると仮定します。
_struct data *data_ptr;
_
list_entry()
マクロは、_data_ptr
_を、ptr
が指す_struct container
_値を保持する_struct data
_値へのポインターに変換するのに役立ちます。
_struct container *cont_ptr = list_entry(data_ptr, struct container, data_item);
_
マクロは、_data_item
_内の_struct container
_のオフセットを計算し、_data_ptr
_ポインターからそのバイト数を減算することによって機能します。これは、_struct container *
_にキャストされると、この特定の_struct container
_を「内部」に保持する_struct data
_への有効なポインターを提供します。
組み込みのoffsetof()
マクロを使用して、マクロを少し簡略化することもできます。
_#define list_entry(ptr, type, member) \
((type *)((char *)(ptr) – offsetof(type, member)))
_
あなたが見つけたこれの説明 ここ:セクションこれはどのように機能しますか?
このマクロは、そのメンバーの1つに指定された構造体のアドレスを見つけるために使用されます。
したがって、たとえば、構造体があるとします。
_typedef struct
{
int i;
int j;
} typestruct;
_
最初に知っておく必要があるのは、マクロの最後の部分です。
_ &((typestruct *)0)->j
_
メンバーのオフセットを与えるために使用されます。つまり、タイプにキャストされたzeroメモリからメンバーまでのサイズ(バイト単位)です。この場合、それはsizeof(int)
です。これは、j
が_int i
_のすぐ下にあるためです。したがって、簡単にするために、この式の値を_4
_と仮定します。マクロでも同じ結果が得られます
_offsetof(typestruct, j);
_
ここで、temp
のアドレスを計算します。ここで、temp
は_typestruct temp
_です。これを行うには、ポインタのアドレスからメンバーの位置を引いたものを単純に計算します。ポインタのアドレスは次のとおりです。
_(typestruct *)((char *) &temp.j)
_
したがって、減算は次のようになります。
_&temp == (typestruct *)((char *) &temp.j) - offsetof(typestruct, j)
_
または、マクロが言うように:
_&temp == (typestruct *)((char *) &temp.j) - &((typestruct *)0)->j
_
あなたはもっと多くを学ぶことができます ここ そしてまたこれで 質問 。
(括弧は必要ですが、説明のために削除されました)