zoukankan      html  css  js  c++  java
  • linux内核链表的使用

    注意这个链表只能在驱动程序中使用

    定义struct list_head {

         struct list_head *prev;

         struct list_head *next;

    };

    初始化链表:

    #define LIST_HEAD_INIT(name)  { &name, &name}

    #define LIST_HEAD(name)
        struct list_head name = LIST_HEAD_INIT(name)

    static struct list_head LIST_HEAD_INIT(head);

    就初始化了一个链表头为head的双链表

    或者使用LIST_HEAD(head) ;一步到位

    添加链表:

    static inline void list_add(struct list_head *new, struct list_head *head)
    {
     __list_add(new, head, head->next);
    }

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

    经过我的分析:list_add(new,head)是将new添加到head后面,应该叫插入head后面

    如果要加入链尾,使用list_add_tail

    static inline void list_add_tail(struct list_head *new, struct list_head *head)
    {
     __list_add(new, head->prev, head);
    }

    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_del(struct list_head *entry)
    {
     __list_del(entry->prev, entry->next);
     entry->next = LIST_POISON1;
     entry->prev = LIST_POISON2;
    }

    static inline void __list_del(struct list_head * prev, struct list_head * next)
    {
     next->prev = prev;
     prev->next = next;
    }

    删除了entry这个链表

    链表的移动:将list节点加到head后面

    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_del_entry(struct list_head *entry)
    {
     __list_del(entry->prev, entry->next);
    }

    static inline void __list_del(struct list_head * prev, struct list_head * next)
    {
     next->prev = prev;
     prev->next = next;
    }

    链表的遍历:

    #define list_for_each_entry(pos, head, member)    
     for (pos = list_entry((head)->next, typeof(*pos), member); 
          &pos->member != (head);  
          pos = list_entry(pos->member.next, typeof(*pos), member))

    #define list_entry(ptr, type, member)
     container_of(ptr, type, member)

    #define container_of(ptr, type, member) ({   
     const typeof(((type *)0)->member) * __mptr = (ptr); 
     (type *)((char *)__mptr - offsetof(type, member)); })

    container_of()实现了根据一个已知结构体成员的指针和变量名得出宿主结构体的地址的功能

    list_entry用于获取struct list_head结构体指针所在结构体变量的首地址

    list_first_entry用于获取链表中第一个节点所在结构体的首地址

    如图:

  • 相关阅读:
    【CF1416D】Graph and Queries(虚点)
    【CF1120D】Power Tree(建图,差分,最小生成树)
    AtCoder Regular Contest 121
    [2021.5] 我要交作业!
    [校内训练2021_03_03]C
    [校内训练2021_03_02]C
    [经验与教训2021_03_01-2021_03_05]
    [校内训练2021_02_24]B,代数数的和仍然是代数数
    [校内训练2021_02_25]C
    [经验与教训2021_02_19-2021_02_26]
  • 原文地址:https://www.cnblogs.com/zhu-g5may/p/10651831.html
Copyright © 2011-2022 走看看