linux内核学习(17)内核编程基本功之内核链表list_entry

内核中链表的使用非常广泛,这里将linux/list.h中的部分,也是最常用的宏定义给总结了。

Pro-III、内核链表:


 

1、定义+初始化:

#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)

{//初始化

list->next = list;

list->prev = list;

}


 

2、添加:


 

static inline void __list_add(struct list_head *new,

struct list_head *prev,

struct list_head *next)

{//[prev]--[new]--[next]

next->prev = new;

new->next = next;

new->prev = prev;

prev->next = new;

}


 

static inline void list_add(struct list_head *new, struct list_head *head)

{//new添加到链表头

__list_add(new, head, head->next);

}

static inline void list_add_tail(struct list_head *new, struct list_head *head)

{//new添加到链表尾

__list_add(new, head->prev, head);

}


 

3、删除:

static inline void __list_del(struct list_head * prev, struct list_head * next)

{//[prev]--[del]--[next]

next->prev = prev;

prev->next = next;

}


 

static inline void list_del(struct list_head *entry)

{//彻底删除

__list_del(entry->prev, entry->next);

entry->next = LIST_POISON1; //指向无效地址

entry->prev = LIST_POISON2;

}


 

static inline void list_del_init(struct list_head *entry)

{//删除+初始化

__list_del(entry->prev, entry->next);

INIT_LIST_HEAD(entry);

}


 

4、移动:

static inline void list_move(struct list_head *list, struct list_head *head)

{//list移到链表最前

__list_del(list->prev, list->next);

list_add(list, head);

}


 

static inline void list_move_tail(struct list_head *list,

struct list_head *head)

{//list移到链表最后

__list_del(list->prev, list->next);

list_add_tail(list, head);

}


 

5、判断:

static inline int list_is_last(const struct list_head *list,

const struct list_head *head)

{//list是否为最后一个

return list->next == head;

}


 

static inline int list_empty(const struct list_head *head)

{//链表是否为空

return head->next == head;

}


 

6、得到结构体:

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

//得到MEMBERTYPE结构体地址之间的差值


 

#define container_of(ptr, type, member) ({ /

const typeof( ((type *)0)->member ) *__mptr = (ptr); /

//定义一个和membe变量类型一样的指针__mptr

(type *)( (char *)__mptr - offsetof(type,member) );})

//显然type结构体的地址肯定比member变量的地址低

//于是减去它们的差值就得到真实type结构体的地址


 

#define list_entry(ptr, type, member) /

container_of(ptr, type, member)

//得到type结构体的地址


 

#define list_first_entry(ptr, type, member) /

list_entry((ptr)->next, type, member)

//得到链表中第一个节点指针


 

7、遍历链表:

#define list_for_each(pos, head) /

for (pos = (head)->next; prefetch(pos->next), pos != (head); /

pos = pos->next)

//prefetch是预取内存的内容,程序员告诉CPU哪些内容可能马上用到,CPU预取,用于优化。


 

#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; prefetch(pos->prev), pos != (head); /

pos = pos->prev)

//向前遍历链表


 

#define list_for_each_safe(pos, n, head) /

for (pos = (head)->next, n = pos->next; pos != (head); /

pos = n, n = pos->next)

//安全遍历,容许有删除操作发生

//设想,假设采用list_for_each(pos,head),如果将pos给删除了

//那么pos=pos->next这条语句就有问题了,pos->next指向一个

//非法的位置(list_del)或者指向了自己(del_del_init),这怎么能容许

//第一种情况在第二次会直接出错,因为pos= LIST_POISON1(非法指针)

//第二种情况直接死循环,因为pos初始化时将next设置为自己了


 

#define list_for_each_prev_safe(pos, n, head) /

for (pos = (head)->prev, n = pos->prev; /

prefetch(pos->prev), pos != (head); /

pos = n, n = pos->prev)

//向前的安全遍历


 

#define list_for_each_entry(pos, head, member) /

for (pos = list_entry((head)->next, typeof(*pos), member); /

prefetch(pos->member.next), &pos->member != (head); /

pos = list_entry(pos->member.next, typeof(*pos), member))

//在遍历的过程中直接使用结构体指针


 

#define list_for_each_entry_reverse(pos, head, member) /

for (pos = list_entry((head)->prev, typeof(*pos), member); /

prefetch(pos->member.prev), &pos->member != (head); /

pos = list_entry(pos->member.prev, typeof(*pos), member))

//向前遍历


 

#define list_for_each_entry_continue(pos, head, member) /

for (pos = list_entry(pos->member.next, typeof(*pos), member); /

prefetch(pos->member.next), &pos->member != (head); /

pos = list_entry(pos->member.next, typeof(*pos), member))

//同样是遍历,但是这里的pos是已经存在的结构体指针,也就是可以从任何节点开始遍历


 

#define list_for_each_entry_safe(pos, n, head, member) /

for (pos = list_entry((head)->next, typeof(*pos), member), /

n = list_entry(pos->member.next, typeof(*pos), member); /

&pos->member != (head); /

pos = n, n = list_entry(n->member.next, typeof(*n), member))

//安全遍历


 

#define list_for_each_entry_safe_continue(pos, n, head, member) /

for (pos = list_entry(pos->member.next, typeof(*pos), member), /

n = list_entry(pos->member.next, typeof(*pos), member); /

&pos->member != (head); /

pos = n, n = list_entry(n->member.next, typeof(*n), member))

//安全遍历,并且可以任意节点遍历

你可能感兴趣的:(linux内核学习(17)内核编程基本功之内核链表list_entry)