内核双向循环链表介绍

来源:互联网 发布:行最简形矩阵的特点 编辑:程序博客网 时间:2024/06/09 19:33

前言

  linux内核通常使用一个名字为(struct list_head)的结构体来实现双向循环链表。struct list_head数据结构如下:

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

  在需要构造双向循环链表的数据结构中加入(struct list_head)成员,然后通过该成员将数据结构连接成双向循环链表。定位时首先找到struct list_head,然后使用container_of找到整个数据结构的起始地址。

1、常用操作函数介绍

(1)初始化链表头,初始化完后,prev和next指针都指向自己。

/*静态初始化*/#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)查找结点。list_for_each用来遍历链表,list_entry用来获取数据结构的起始地址,然后我们就可以判断该结点是不是我们要查找的了。

#define list_entry(ptr, type, member) \    container_of(ptr, type, member)#define list_for_each(pos, head) \    for (pos = (head)->next; pos != (head); pos = pos->next)#define list_for_each_r(pos, head) \    for (pos = (head)->prev; pos != (head); pos = pos->prev) 

(3)添加结点

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);} 

(4)删除结点

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);    entry->next = LIST_POISON1;    entry->prev = LIST_POISON2;}

(5)判断链表是否为空

static inline int list_empty(const struct list_head *head){    return head->next == head;}

(6)合并两个链表

static inline void __list_splice(struct list_head *list,                 struct list_head *head){    struct list_head *first = list->next;    struct list_head *last = list->prev;    struct list_head *at = head->next;    first->prev = head;    head->next = first;    last->next = at;    at->prev = last;}static inline void list_splice(struct list_head *list, struct list_head *head){    if (!list_empty(list))        __list_splice(list, head);}

2、使用例子

int main(void) {    struct list_head head, *plist;    struct student *node;    INIT_LIST_HEAD(&head);    list_add(&stu[0].list, &head);    list_add(&stu[1].list, &head);    list_add(&stu[2].list, &head);    list_add(&stu[3].list, &head);    list_add(&stu[4].list, &head);    list_for_each(plist, &head) {        node = list_entry(plist, struct student, list);        print_message(node);    }    return 0;}
0 0
原创粉丝点击