昨天看ttm的时候看到一个内核中的经典用法:
struct ttm_agp_backend {
struct ttm_tt ttm;
struct agp_memory *mem;
struct agp_bridge_data *bridge;
};
static int ttm_agp_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem)
{
struct ttm_agp_backend *agp_be = container_of(ttm, struct ttm_agp_backend, ttm);
...
}
原型:
#define container_of(ptr, type, member) ({ \
void *__mptr = (void *)(ptr); \
BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && \
!__same_type(*(ptr), void), \
"pointer type mismatch in container_of()"); \
((type *)(__mptr - offsetof(type, member))); })
typeof(member)* container_of(ptr, type, member) {
void *__mptr = (void *)(ptr);
BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) &&!__same_type(*(ptr), void), "pointer type mismatch in container_of()");
return (type *)(__mptr - offsetof(type, member));
}
参数介绍:
- ptr:一个结构体中的指针。
- type:ptr所在结构体的类型。
- member:ptr
函数解析:
- void *__mptr = (void *)(ptr);
将prt的首地址给__mptr。
- BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) &&!__same_type(*(ptr), void), "pointer type mismatch in container_of()");
判断ptr是否为type结构体中的成员。
- offsetof(type, member);
//获取member在它所在结构体中的地址偏移量x。
- (type *)(__mptr - offsetof(type, member));
__mptr的地址减去地址偏移量x即可得出ptr所在结构体变量的首地址。并强制转换该首地址成type类型的指针。
结论
container_of(ptr, type, member)在ptr和member为同一个指针的情况下,可以用来找出ptr所在结构体变量的首地址。
参考:https://blog.csdn.net/s2603898260/article/details/79371024