内核链表虽然本质上还是双向循环链表但它不同于一般的双向循环链表
一般我们设置双向循环链表的结构体为
typedef struct sxxh
{
int data;
struct sxxh * prev;
struct sxxh *next;
} sxxh_t,*psxxh_t;
而内核链表,相对来说它没有数据域,对它而言是直接对前后的地址进行操作,
struct list_head{
struct list_head *prev;
struct list_head *next;
};
struct maxcore{
int data;
struct list_head list;
}
它通过子结构体地址去寻找父结构体的地址
在list.h文件体现为
#define list_entry(ptr, type, member)
ptr: 传进来的小结构体地址
type:大结构体的类型
member:大结构体下的成员,也就是list
一旦调用这个宏: list_entry(ptr, type, member)
const typeof( ((type *)0)->member ) *__mptr = (ptr) ;
(type *)( (char *)__mptr - ((size_t) &((TYPE *)0)->MEMBER);
解释:
*** const typeof( ((type *)0)->member ) *__mptr = (ptr) ;
将取的的小结构体指针类型命名为__mptr 再将ptr的内容给__mptr
(char *)__mptr
将小结构体指针类型的__mptr转为char*类型
*** ((size_t) &((TYPE *)0)->MEMBER)
((TYPE *)0)-->将0强转为 大结构体指针类型(以0为大结构体起始地址,仅起参照作用不是真的在0x0000这里)
&((TYPE *)0)->MEMBER)-->得到大结构体中小结构体的地址 ,该小结构体地址与ptr中的是同一个
(size_t)&((TYPE *)0)->MEMBER) -->将取得大结构体中的小结构体的地址,强转为无符号整数
得到该成员(小结构体)相对于大结构体的偏移量
*** (char *)__mptr - ((size_t) &((TYPE *)0)->MEMBER
通过 小结构体的地址 与 小结构体 相对于 大结构体的 偏移量 的差,得到大结构体的地址数值
*** (type *)( (char *)__mptr - ((size_t) &((TYPE *)0)->MEMBER);
转化为大结构体的地址类型,就相当于找到了传进来的小结构体的大结构体的地址