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用于获取链表中第一个节点所在结构体的首地址

    如图:

  • 相关阅读:
    Java 学习总结(一)
    每日学习心得:SharePoint 为列表中的文件夹添加子项(文件夹)、新增指定内容类型的子项、查询列表中指定的文件夹下的内容
    每日学习心得:SharePoint 2013 自定义列表项添加Callout菜单项、文档关注、SharePoint服务端对象模型查询
    HighCharts使用心得
    ECharts使用心得总结(二)
    每日学习心得:Js基本数据类型常用方法扩展
    每日学习心得:$.extend()方法和(function($){...})(jQuery)详解
    Mustache 使用心得总结
    Extjs editor 设置默认值
    Ext this.getView(...).saveDocumentAs is not a function
  • 原文地址:https://www.cnblogs.com/zhu-g5may/p/10651831.html
Copyright © 2011-2022 走看看