首先定位到bnxt_re的驱动代码,或者其它相关代码也行,
struct bnxt_re_dev *rdev;
/* Allocate bnxt_re_dev instance here */
rdev = ib_alloc_device(bnxt_re_dev, ibdev);
再接着展开ib_alloc_device,
#define ib_alloc_device(drv_struct, member) \
container_of(_ib_alloc_device(sizeof(struct drv_struct) + \
BUILD_BUG_ON_ZERO(offsetof( \
struct drv_struct, member))), \
struct drv_struct, member)
其实就是:
container_of(_ib_alloc_device(sizeof(struct drv_struct) + BUILD_BUG_ON_ZERO(offsetof(struct drv_struct, member))), struct drv_struct, member)
这里涉及到了_ib_alloc_device函数,以及BUILD_BUG_ON_ZERO宏,
关于这个宏是这样的,
BUILD_BUG_ON_ZERO(0);//编译通过
BUILD_BUG_ON_ZERO(1);//编译失败
所以,offsetof返回的应该就是0,也就是说ibdev这个成员在结构体bnxt_re_dev的定义当中,位置在第一位,也就是偏移量为0。
所以,变成了下面这样。
container_of(ib_device, bnxt_re_dev, ibdev);
本质是最后返回bnxt_re_dev结构体的起始地址,当然,
在_ib_alloc_device函数里面,它已经kzalloc了,并且大小是以bnxt_re_dev为基准的,所以,就要求ibdev一定要在
bnxt_re_dev结构体的首位。
struct ib_device *_ib_alloc_device(size_t size)
{
struct ib_device *device;
unsigned int i;
if (WARN_ON(size < sizeof(struct ib_device)))
return NULL;
device = kzalloc(size, GFP_KERNEL);
if (!device)
return NULL;
//.....
return device;
}
EXPORT_SYMBOL(_ib_alloc_device);
虽然返回了struct ib_device *类型,但是它申请的size是szieof(bnxt_re_dev),所以
本质上其实也就相当于malloc了一个bnxt_re_dev结构体。
参考:
https://blog.csdn.net/u012028275/article/details/127478561
https://www.runoob.com/cprogramming/c-macro-offsetof.html
https://www.cnblogs.com/dongxb/p/14155000.html