您的位置:首页 > 运维架构 > Linux

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

2011-01-09 20:37 447 查看
内核中链表的使用非常广泛,这里将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)
//得到MEMBER和TYPE结构体地址之间的差值


#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))
//安全遍历,并且可以任意节点遍历
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐