为了理解list_entry,先定义一个结构体: struct student{ char name[100]; int num; struct list_head list; };
原型: #define list_entry(ptr, type, member) \ container_of(ptr, type, member)
参数: ptr是指向struct list_head的指针 type是自己定义的struct类型,里面包含一个struct list_head类型的成员 member是一个struct list_head类型的变量
作用:在使用list的时候我们得到的时list的指针,需要通过list指针获得 自己定义的结构体变量的起始地址。
container_of(ptr, type, member)的原型: #define container_of(ptr, type, member) ({ \ const typeof(((type *)0)->member) * __mptr = (ptr); \ (type *)((char *)__mptr - offsetof(type, member)); })
假设我们自己定义了一个student struct student stu; 已知stu.list的指针pstu;
container_of(pstu, struct student, list)
const typeof(((type *)0)->member) * __mptr = (ptr); 解释: 定义一个指针__mptr,类型为typeof(((type *)0)->member), 初始值ptr 这里使用虚拟地址0x0,强制转换为type类型的指针(即struct student),通过 ((struct student *)0)->list 获得成员list,再用typeof获得类型。
offsetof(type, member) //获取偏移量,原型在后面说明 获得member到type的偏移量,对上面的例子来说就是获得 &stu 和 &(stu.list) 之间的距离。
(type *)((char *)__mptr - offsetof(type, member)); __mptr减去偏移量即可获得stu的起始地址。
offsetof(type, member)原型: #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 解释: 使用虚拟地址0x0,强制转换为type类型的指针(即struct student);因为是从0x0开始计算,所以 MEMBER的地址在数值上就等于偏移量。 |