链表是一种重要的数据结构,应用的非常广泛。链表分为单向链表与双向链表,一般的实现就是在结构体中内嵌指向下一个元素的指针。例如:
- struct name {
- int num;
- ...;
- struct name *next;
- struct name *prev;
- }
list.h中首先定义了这样一个结构体,这个是链表的基本结构:
- struct list_head {
- struct list_head *next, *prev;
- };
- struct my_struct {
- int a;
- int b;
- ...
- struct list_head list;
- }
- #define LIST_HEAD_INIT(name) { &(name), &(name) }
- #define LIST_HEAD(name) \
- struct list_head name = LIST_HEAD_INIT(name)
- #define INIT_LIST_HEAD(ptr) do { \
- (ptr)->next = (ptr); (ptr)->prev = (ptr); \
- } while (0)
定义了一个链表后,最重要的操作是向链表添加元素,与删除元素以及遍历链表。下面先说添加元素的操作:
- static inline void __list_add(struct list_head *new,
- struct list_head *prev,
- struct list_head *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)
- {
- __list_add(new, head, head->next);
- }
- static inline void list_add_tail(struct list_head *new, struct list_head *head)
- {
- __list_add(new, head->prev, head);
- }
向链表添加元素只知道链表的头与新的元素地址就可以了,因为链表是双向循环链表,链表头的前一个元素就是这个链表的最后一个元素。list_add是将新元素添加到链表头的后面,而list_add_tail是将心元素添加到链表的尾部,这两个操作如下图所示:
图 1 list_add操作
图 2 list_add_tail操作
说完了添加元素,下面说一下如何删除链表元素,如下:
- static inline void __list_del(struct list_head *prev, struct list_head *next)
- {
- next->prev = prev;
- prev->next = next;
- }
- static inline void list_del(struct list_head *entry)
- {
- __list_del(entry->prev, entry->next);
- }
list_head链表最重要的特点就是链表操作与结构体分离,用list_head链接的链表结构上如下图所示:
![](https://img-my.csdn.net/uploads/201205/31/1338473075_7871.png)
- for ( mylist = mylist_head->next; mylist != mylist_head; mylist = mylist->next);
- #define list_entry(ptr, type, member) \
- ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
- struct my_struct {
- int a;
- char b;
- ...
- strcut list_head list;
- }
struct my_struct *ptr = list_entry(plist, struct my_struct, list);
list_entry宏实现的非常巧妙,括号比较多,让我们将这个宏分解来看。
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
最外面的一层括号可以去掉,这是为了防止宏扩展的,去掉如下:
(type *) ((char *)(ptr)-(unsigned long)(&((type *)0)->member))
现在就比较清楚了,首先(type *)是C强制转换操作,就是将后面的的数据转化成type结构的指针。而后面的操作可以再分解
(char *)(ptr) - (unsigned long)(&((type *)0)->member)
这样就是一个减法的操作,前面是一个指针,我们传过去的结构体元素的指针,这里被转化成指向字符的。而后面是一个长整形,可以再分解
(unsigned long) (&((type *)0)->member)
显然这个长整形是一个指针转化的,而这个指针又可以再分解,
&((type *)0)->member
可以看出这个指针是一个变量取地址得到的,这个变量又是什么呢
((type *)0)->member
看起来有点奇怪,不过这个操作是整个宏中最精妙的,他将地址0转化成type类型,接下来又取得这个结构的member元素,member就是我们传进来的参数:元素在结构体中的命名。其实((type *)0)->member取的变量是内容是什么一点都不重要,重要的我们要取这个变量的地址。取完这个地址将它转换成unsigned long类型,这样这个数据就是((type *)0)->member相对与地址0的偏移。回到上面的那个减法,将结构体中元素的地址与他与结构体首地址的偏移相减,不就得到了结构体的地址了吗。整个操作如下图所示:
![](https://img-my.csdn.net/uploads/201205/31/1338473290_4041.png)
双向链表在Linux内核中的实现
-
- struct
list_head { -
struct 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) - {
-
list->next = list; -
list->prev = list; - }
- static
inline void __list_add(struct list_head *new, -
struct list_head *prev, -
struct list_head *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) - {
-
__list_add(new, head, head->next); - }
- static
inline void list_add_tail(struct list_head *new, struct list_head *head) - {
-
__list_add(new, head->prev, head); - }
- static
inline void __list_del(struct list_head * prev, struct list_head * next) - {
-
next->prev = prev; -
prev->next = next; - }
- static
inline void __list_del_entry(struct list_head *entry) - {
-
__list_del(entry->prev, entry->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(entry); -
INIT_LIST_HEAD(entry); - }
- #define
LIST_POISON1 ((void *) 0x00100100 + POISON_POINTER_DELTA) - #define
LIST_POISON2 ((void *) 0x00200200 + POISON_POINTER_DELTA)
- static
inline void list_replace(struct list_head *old, -
struct list_head *new) - {
-
new->next = old->next; -
new->next->prev = new; -
new->prev = old->prev; -
new->prev->next = new; - }
-
- static
inline void list_replace_init(struct list_head *old, -
struct list_head *new) - {
-
list_replace(old, new); -
INIT_LIST_HEAD(old); - }
- static
inline void list_move(struct list_head *list, struct list_head *head) - {
-
__list_del_entry(list); -
list_add(list, head); - }
- static
inline void list_move_tail(struct list_head *list, -
struct list_head *head) - {
-
__list_del_entry(list); -
list_add_tail(list, head); - }
- static
inline int list_is_last(const struct list_head *list, -
const struct list_head *head) - {
-
return list->next == head; - }
- static
inline int list_empty(const struct list_head *head) - {
-
return head->next == head; - }
- static
inline int list_empty_careful(const struct list_head *head) - {
-
struct list_head *next = head->next; -
return (next == head) && (next == head->prev); - }
- static
inline void list_rotate_left(struct list_head *head) - {
-
struct list_head *first; -
-
if (!list_empty(head)) { -
first = head->next; -
list_move_tail(first, head); -
} - }
- static
inline int list_is_singular(const struct list_head *head) - {
-
return !list_empty(head) && (head->next == head->prev); - }
- static
inline void __list_cut_position(struct list_head *list, -
struct list_head *head, struct list_head *entry) - {
-
struct list_head *new_first = entry->next; -
list->next = head->next; -
list->next->prev = list; -
list->prev = entry; -
entry->next = list; -
head->next = new_first; -
new_first->prev = head; - }
- static
inline void list_cut_position(struct list_head *list, -
struct list_head *head, struct list_head *entry) - {
-
if (list_empty(head)) -
return; -
if (list_is_singular(head) && -
(head->next != entry && head != entry)) -
return; -
if (entry == head) -
INIT_LIST_HEAD(list); -
else -
__list_cut_position(list, head, entry); - }
- static
inline void __list_splice(const struct list_head *list, -
struct list_head *prev, -
struct list_head *next) - {
-
struct list_head *first = list->next; -
struct list_head *last = list->prev; -
-
first->prev = prev; -
prev->next = first; -
-
last->next = next; -
next->prev = last; - }
- static
inline void list_splice(const struct list_head *list, -
struct list_head *head) - {
-
if (!list_empty(list)) -
__list_splice(list, head, head->next); - }
- static
inline void list_splice_tail(struct list_head *list, -
struct list_head *head) - {
-
if (!list_empty(list)) -
__list_splice(list, head->prev, head); - }
- static
inline void list_splice_init(struct list_head *list, -
struct list_head *head) - {
-
if (!list_empty(list)) { -
__list_splice(list, head, head->next); -
INIT_LIST_HEAD(list); -
} - }
- static
inline void list_splice_tail_init(struct list_head *list, -
struct list_head *head) - {
-
if (!list_empty(list)) { -
__list_splice(list, head->prev, head); -
INIT_LIST_HEAD(list); -
} - }
- #define
list_entry(ptr, type, member) \ -
container_of(ptr, type, member) - #define
list_first_entry(ptr, type, member) \ -
list_entry((ptr)->next, type, member)
- #define
list_for_each(pos, head) \ -
for (pos = (head)->next; prefetch(pos->next), pos != (head); \ -
pos = pos->next) - #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) - #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_prepare_entry(pos, head, member) \ -
((pos) ? : list_entry(head, 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)) - #define
list_for_each_entry_continue_reverse(pos, head, member) \ -
for (pos = list_entry(pos->member.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_from(pos, head, member) \ -
for (; prefetch(pos->member.next), &pos->member != (head); \ -
pos = list_entry(pos->member.next, typeof(*pos), member))
- #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)) - #define
list_for_each_entry_safe_from(pos, n, head, member) \ -
for (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_reverse(pos, n, head, member) \ -
for (pos = list_entry((head)->prev, typeof(*pos), member), \ -
n = list_entry(pos->member.prev, typeof(*pos), member); \ -
&pos->member != (head); \ -
pos = n, n = list_entry(n->member.prev, typeof(*n), member))
- #define
list_safe_reset_next(pos, n, member) \ -
n = list_entry(pos->member.next, typeof(*pos), member)
http://blog.csdn.net/yaozhenguo2006/article/details/7621551
http://blog.sina.com.cn/s/blog_63ad891e0101aymv.html