Linux内核经典链表list_head常用方法总结

前言:一起分析内核最重要的链表list_head

一、链表结构

struct list_head {
	struct list_head *next, *prev;
};

二、链表初始化函数

list_head 链表的初始化只是把 *next, *prev连个指针指向链表头,形成双向循环链表;

#define LIST_HEAD_INIT(name) { &(name), &(name) }
 
#define LIST_HEAD(name) \
	struct list_head name = LIST_HEAD_INIT(name)
 
static inline void INIT_LIST_HEAD(struct list_head *list)
{
	WRITE_ONCE(list->next, list);
	list->prev = list;
}

上面是各种不同的初始化或者定义并初始化链表的函数,我们都可以使用,
例如:
1)我们自己定义一个链表头,然后调用函数初始化:

struct list_head name;
LIST_HEAD_INIT(name)//INIT_LIST_HEAD(name);

2)或者使用下面宏定义并初始化一个双向循环链表头;

 LIST_HEAD(name)

三、增、删、遍历接口

我们都知道链表是用来保存一下有意义的字段的,但是list_haed结构中并没有其他字段,所以内核使用该链表时,总是把它嵌套到一个宿主结构中来使用。例如:

struct  zj_list{
    int val ;
    struct list_head mylist;
}

3.1 增加节点

内核中提供了添加一个节点的接口,如下:

static inline void list_add(struct list_head *new, struct list_head *head)//首插入
static inline void list_add_tail(struct list_head *new, struct list_head *head)//尾插入

3.2 删除节点

static inline void list_del(struct list_head *entry)

3.3 遍历链表

内核是同过下面这个宏定义来完成对list_head链表进行遍历的,如下 :

#define list_for_each(pos, head)  for (pos = (head)->next; pos != (head); pos = pos->next`) //从前往后
#define list_for_each_prev(pos, head) for (pos = (head)->prev; pos != (head); pos = pos->prev) //从后往前

3.4 定位宿主

上面的所有操作都是基于list_head这个链表进行的,涉及的结构体也都是该结构体,但是我们知道,这个结构体是嵌入到别的宿主中使用的,所以我们应该定位到该结构体的宿主位置,内核中有定义宏去直接得到宿主的地址,如下:
作用:已知某结构体的成员member和指向该成员的指针ptr(也就是member的地址),算出该结构体的起始地址。

 #define container_of(ptr,type,member)
{const typeof(((type*)0)->member)* _myptr=(ptr);
(type*)((char*)_myptr-offsetof(type,member));})

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE*)0)->MEMBER)

我们分析上面这个宏,发现有好些都不认识,这里一个一个分析:
( (TYPE *)0 ) 将零转型为TYPE类型指针;
((TYPE *)0)->MEMBER 访问结构中的数据成员;
&( ( (TYPE )0 )->MEMBER )取出数据成员的地址;,因为是从0开始的,所以就相当于该成员在结构体中的偏移量。
(size_t)(&(((TYPE
)0)->MEMBER))结果转换类型;
typeof为C语言的关键字,用来由变量得到变量的类型,eg;typeof(a)得到变量a的类型。

经过上面分析可以看出来,其实现就是通过mem成员的地址减去mem的偏移量,来得到首地址,即宿主的地址。

3.5 宿主结构的遍历

宿主结构的遍历,它们的实现都是利用list_entry宏。

#define list_entry((ptr)->next, type, member)  	container_of(ptr,type,member)
#define list_for_each_entry(pos, head, member)                \
    for (pos = list_entry((head)->next, typeof(*pos), member);    \
         &pos->member != (head);     \
         pos = list_entry(pos->member.next, typeof(*pos), member))
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值