container_of
は Linux カーネルでよく見られ、実際のドライバー作成でも広く使用されています。
##Function: 構造体の メンバーを介した変数address は、 構造体の最初のアドレス を検索します。
は次のように定義されます:/** * container_of - cast a member of a structure out to the containing structure * @ptr: the pointer to the member. * @type: the type of the container struct this is embedded in. * @member: the name of the member within the struct. * */ #define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );})
: 構造体メンバ変数へのポインタ
: 構造体の型
: 構造体のメンバ変数名
既知の構造体 type のメンバー
member のアドレス ptr がわかっており、構造体
type の開始アドレス
解決されます。
計算式は次のとおりです。 type
の開始アドレス = ptr
-size
(size はメンバーのサイズです)
図を使用して、ptr
、type
、member
の関係を示します:
container_of
の利点は、 が 0
を次のように使用することです。メンバ変数 メンバ
のベースアドレスはです。
中間変数 __mptr
が定義されており、「__
」は内部使用を表し、「m
」は middle
を表します。
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
typeof( ((type *)0)->member )
是获取member
的类型,__mptr = (ptr)
判断ptr
与member
是否为同一类型,offsetof
计算成员member
的大小size
。
例如内核的pwm
驱动,通过成员变量chip
,找到结构体bcm2835_pwm
:
struct bcm2835_pwm { struct pwm_chip chip; struct device *dev; void __iomem *base; struct clk *clk; }; static inline struct bcm2835_pwm *to_bcm2835_pwm(struct pwm_chip *chip_ptr) { return container_of(chip_ptr, struct bcm2835_pwm, chip); }
使用container_of
通常都会定义一个函数,并且命名为to_xxx
或者to_find_xxx
,代表要找xxx
这个结构体,传参则传入成员变量指针,另外函数也会声明为inline
。
以上がLinux カーネルの基礎 - コンテナーの原理と実際の応用の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。