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

    技术2022-06-27  91

    内核中链表的使用非常广泛,这里将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))

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


    最新回复(0)