Linux 内核 --offsetof 和 container_of

1
#define offsetof(type, member)  ((size_t)&((type *)0)->member)

offsetof:获取结构体中成员的偏移位置,将地址 0 强制转换为 type 类型的指针(编译器认为 0 是一个有效地址,即 0type指针的起始地址),然后再引用 member 成员(对应的就是 ((type *)0)->member,即偏移到member 成员的起始地址),最后将 member 成员的起始地址强制转换为 size_t 类型

Consider this example:

1
2
3
4
struct Test {
char text[32];
int count;
}

If struct Test is allocated at the address 0xC000, then the address of text would be 0xC000, and the address of count would be 0xC020. However, if the base address is zero (which is not allowed by the standard), then the address of text would be zero, and the address of the count would be 0x20. Casting these addresses to size_t gives you the offset of the corresponding members.

1
2
3
4
5
6
7
8
9
10
/**
* 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) );})

container_ofconst typeof(((type *)0)->member ) *__mptr = (ptr);通过 typeof 定义一个 member 指针类型的指针变量 __mptr(即__mptr 是指向 member 类型的指针),并将 __mptr 赋值为 ptr(type *)((char *)__mptr - offsetof(type,member)); 通过 offsetof 宏计算出 membertype中的偏移,然后用 member 的实际地址 __mptr 减去偏移,得到 type 的起始地址,即指向 type 类型的指针


Linux 内核 --offsetof 和 container_of
https://silhouettesforyou.github.io/2021/11/12/f47f5e2db501/
Author
Xiaoming
Posted on
November 12, 2021
Licensed under