内核链表

内核链表是一种特殊的双向循环链表,不包含数据域,而是通过指针直接操作前后节点。list_entry宏用于从链表节点找到包含该节点的结构体,通过计算偏移量得到大结构体的地址。这种方法在Linux内核中常见,提高了代码的灵活性和效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

内核链表虽然本质上还是双向循环链表但它不同于一般的双向循环链表

一般我们设置双向循环链表的结构体为

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);
        
            转化为大结构体的地址类型,就相当于找到了传进来的小结构体的大结构体的地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值