内核链表是一个doubly linked list,是一个双向循环链表。Linux使用链表时,将链表放入数据结构中。头文件:<linux/list.h>
链表头定义在<linux/types.h>
1 2 3  | struct list_head {    struct list_head *next, *prev;}; | 
所有的链表操作,均是操作list_head结构体,而不操作包含它的数据结构。
链表的每一个项都是上述数据结构,但是Linux的设计是有一个专门的头,其不包含数据,仅用于维护链表,其它的链表项则包含数据。
如上述,如果知道A狐狸的list成员,是可以遍历整个链表,但是不知道哪个是头,哪个是包含数据的链表项。因此我们始终需要知道head。
使用list_entry()宏:
1 2 3 4 5 6  | #define list_entry(ptr, type, member) \    container_of(ptr, type, member)// examplestruct list_head *list = &A.list;list_entry(list, struct fox, list); | 
list_first_entry(ptr, type, member)
获取第一个节点,ptr通常是链表头。
链表头初始化时,next和prev均指向它自己。
有3种方式,其实现代码如下:
1 2 3 4 5 6 7 8 9 10  | #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  | static LIST_HEAD(fox_head); | 
如果头是结构体的成员,并动态初始化:
1  | INIT_LIST_HEAD(inode->inotify_watches); | 
如果头是结构体成员,并编译期间静态初始化:
1 2 3 4  | struct inode inode = {    .inotify_watches = LIST_HEAD_INIT(inode.inotify_watches),}; | 
所有这些函数,均为内联函数,实现在linux/list.h头文件中。
内核链表还有一个重要的特点是,它的prev和next绝不为Null,这极大的优化了链表维护的代码。
所有的链表操作函数内部都没有锁保护,需要根据上下文,自己添加锁保护。
将一个节点添加到head之后,该节点为第一个节点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14  | 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);} | 
将一个节点添加到head之前,该节点成为最后一个节点。
1 2 3 4  | static inline void list_add_tail(struct list_head *new, struct list_head *head){        __list_add(new, head->prev, head);} | 
删除一个节点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20  | static inline void __list_del(struct list_head * prev, struct list_head * next){    next->prev = prev;    WRITE_ONCE(prev->next, next);}static inline void __list_del_entry(struct list_head *entry){    if (!__list_del_entry_valid(entry))        return;    __list_del(entry->prev, entry->next);}static inline void list_del(struct list_head *entry){    __list_del_entry(entry);    entry->next = LIST_POISON1;    entry->prev = LIST_POISON2;} | 
删除节点后,next和prev被赋予一个特殊的值,而不是NULL,这是出于调试目的。
删除之后,再进行头初始化。
替换节点
1 2 3 4 5 6 7 8  | 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;} | 
替换后,在进行头初始化。
将list从现链表删除,然后插入到head链表
void list_move(struct list_head *list, struct list_head *head)
将list从现链表删除,然后插入到head链表尾
void list_move_tail(struct list_head *list,
struct list_head *head)
链表是否是最后一个节点(判断next是否为头)
int list_is_last(const struct list_head *list,
const struct list_head *head)
链表是否为空(判断next是否为头自己)
int list_empty(const struct list_head *head)
判断链表是否只有一个节点
int list_is_singular(const struct list_head *head)
将下一个节点移动为上一个节点
void list_rotate_left(struct list_head *head)
将head之后的节点直到entry,移动到空链表list
void list_cut_position(struct list_head *list,
struct list_head *head, struct list_head *entry)
将list链表合并到head之后:
void list_splice(const struct list_head *list,
struct list_head *head)
list_splice_tail()
list_splice_init()
list_splice_tail_init()
带tail的合并到head之前,带init的合并后,对list进行头初始化。
遍历链表需要提供一个变量存储当前cursor。对于safe类接口,还需要一个变量存储下一个节点。
1 2 3 4 5 6 7 8 9 10 11  | #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)#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; \             pos != (head); \             pos = n, n = pos->prev) | 
prev类是反向遍历。如果需要删除遍历出的当前节点,需要使用safe类接口,它将当前节点的下一个遍历节点存储起来,这样删除了当前节点,也可以继续遍历。
上述4个接口,获取的是list_head的指针,通常获取其父结构的指针更为便利,有对应的接口:
1 2 3 4  | list_for_each_entry(pos, head, member) list_for_each_entry_reverse(pos, head, member) list_for_each_entry_safe(pos, n, head, member) list_for_each_entry_safe_reverse(pos, n, head, member) | 
从一个特定节点之后开始搜索:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22  | #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);  \             &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);  \             &pos->member != (head);    \             pos = list_entry(pos->member.prev, typeof(*pos), member))#define list_for_each_entry_from(pos, head, member)                     \        for (; &pos->member != (head);  \             pos = list_entry(pos->member.next, typeof(*pos), 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)) | 
list_prepare_entry(),如果pos为空,则head的父结构,否则为pos。注意:如果head不是放在父结构中的,这里也没关系,假设有一个父结构,可以安全的使用list_for_each_entry_continue(),它从下一个节点开始遍历,使用一个假的父结构指针也是可以获取下一个节点的,但是不能使用list_for_each_entry_from()。
list_for_each_entry_continue(),从pos的下一个节点开始遍历
list_for_each_entry_continue_reverse,从pos的上一个节点开始反向遍历
list_for_each_entry_from(),从pos本身开始遍历
list_for_each_entry_safe_continue(),safe版本
list_for_each_entry_safe_from(),safe版本
重置next为pos的next
1 2  | #define list_safe_reset_next(pos, n, member)                            \        n = list_entry(pos->member.next, typeof(*pos), member) | 
参考:
Robert Love. Linux Kernel Development. Third Edition