• 【内核】内核链表使用说明,list.h注释


    list_entry定义

    /**
    * list_entry - get the struct for this entry
    * @ptr:        the &struct list_head pointer.
    * @type:       the type of the struct this is embedded in.
    * @member:     the name of the list_struct within the struct.
    */
    #define list_entry(ptr, type, member) /
            ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))

      在Linux内核中,函数list_entry()用来获取节点地址.

      其不难理解为:从一个结构的成员指针找到其容器的指针。 

    1. ptr是找容器的那个变量的指针,把它减去自己在容器中的偏移量的值就应该 得到容器的指针。(容器就是包含自己的那个结构)。
    2. 指针的加减要注意类型,用(char*)ptr是为了计算字节偏移。
    3. ((type *)0)->member是一个小技巧。
    4. 前面的(type *)再转回容器的类型。
    #define list_entry(ptr, type, member) /
            ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))
    • ptr是指向list_head类型链表的指针
    • type为一个结构
    • 而member为结构type中的一个域,类型为list_head
    • 这个宏返回指向type结构的指针

      在内核代码中大量引用了这个宏,因此,搞清楚这个宏的含义和用法非常重要。

    设有如下结构体定义:

    typedef struct xxx
    {
         ……(结构体中其他域,令其总大小为size1)
         type1 member;
         ……(结构体中其他域)
    }type;

    定义变量:

    type a;
    type * b;
    type1 * ptr;

    执行:

    ptr=&(a.member);
    b=list_entry(ptr,type,member);

      这样就使b指向a,得到了a的地址

    如何做到的呢?

    &((type *)0)->member

      把“0”强制转化为指针类型,则该指针一定指向“0”(数据段基址)。

      因为指针是“type *”型的,所以可取到以“0”为基地址的一个type型变量member域的地址。

      那么这个地址也就等于member域到结构体基地址的偏移字节数。

     ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))

      (char *)(ptr)使得指针的加减操作步长为一字节,(unsigned long)(&((type *)0)->member)等于ptr指向的member到该member所在结构体基地址的偏移字节数。二者一减便得出该结构体的地址。转换为 (type *)型的指针,便大功告成。 


    list.h注释

      每一个熟悉内核的程序员,写出来的程序会更加优美和高效,因为内核代码本身就是优美和高效的,我们可以加以借荐;

      但是内核的庞大程度与复杂的各种结构使很多人望而生畏,因此我把经常使用的内核链表核心文件给加了注释,以方便使用。

      1 //################  注释:By 成鹏致远     ################//
      2 //################  net :infodown.tap.cn ################//
      3 //################  time:2013-7-30       ################//
      4 
      5 
      6 #ifndef __DLIST_H
      7 #define __DLIST_H
      8 
      9 /* This file is from Linux Kernel (include/linux/list.h)    //————————>位置
     10 * and modified by simply removing hardware prefetching of list items.    //————————>在预处理阶段对链表项进行替换
     11 * Here by copyright, credits attributed to wherever they belong.
     12 * Kulesh Shanmugasundaram (kulesh [squiggly] isis.poly.edu)
     13 */
     14 
     15 /*
     16 * Simple doubly linked list implementation.    //————————>简单的双向链表实现
     17 *
     18 * Some of the internal functions (“__xxx”) are useful when
     19 * manipulating whole lists rather than single entries, as    //————————>最好对整个链表进行操作
     20 * sometimes we already know the next/prev entries and we can
     21 * generate better code by using them directly rather than
     22 * using the generic single-entry routines.
     23 */
     24 
     25 
     26 //################ 通过内部结构指针返回外部容器指针 ################//
     27 /**
     28  * container_of - cast a member of a structure out to the containing structure    //————————>container_of:从一个结构的成员指针找到其容器的指针
     29  *
     30  * @ptr:    the pointer to the member.    //————————>ptr:指向menber的指针,即找容器的那个变量的指针
     31  * @type:    the type of the container struct this is embedded in.    //————————>type:容器的类型
     32  * @member:    the name of the member within the struct.    //————————>member:容器中struct类型成员
     33  *
     34  */
     35 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)            //————————>offsetof:TYPE结构类型中MEMBER结构指针与TYPE结构指针的偏移量
     36 
     37 #define container_of(ptr, type, member) ({                                //————————>container_of:从一个结构的成员指针找到其容器的指针
     38         const typeof( ((type *)0)->member ) *__mptr = (ptr);            //————————>ptr:指向menber的指针,即找容器的那个变量的指针
     39         (type *)( (char *)__mptr - offsetof(type,member) );})            //————————>type:容器的类型
     40                                                                         //————————>member:容器中struct类型成员
     41 
     42 
     43 
     44 
     45 
     46 //################ 链表初始化 ################//
     47 /*
     48  * These are non-NULL pointers that will result in page faults    //————————>野指针会导致页面出错
     49  * under normal circumstances, used to verify that nobody uses    //————————>以下初始化方法保证了不会出现野指针(确认没有空指针传入)
     50  * non-initialized list entries.
     51  */
     52 #define LIST_POISON1  ((void *) 0x00100100)
     53 #define LIST_POISON2  ((void *) 0x00200
     54 
     55 struct list_head {    //————————>内核链表结构
     56     struct list_head *next, *prev;
     57 };
     58 
     59 #define LIST_HEAD_INIT(name) { &(name), &(name) }    //————————>LIST_HEAD_INIT(name):用name来初始化链表
     60 
     61 #define LIST_HEAD(name)     //————————>LIST_HEAD(name):间接用LIST_HEAD_INIT(name)来初始化链表,本质:LIST_HEAD(name)用来定义+初始化
     62 struct list_head name = LIST_HEAD_INIT(name)
     63 
     64 #define INIT_LIST_HEAD(ptr) do {     //————————>运行时初始化,功能相同:初始化
     65     (ptr)->next = (ptr); (ptr)->prev = (ptr); 
     66 } while (0)
     67 
     68 
     69 
     70 
     71 
     72 
     73 //################ 链表插入算法 ################//
     74 /*
     75 * Insert a new entry between two known consecutive entries.    //————————>在两个连续的结点间插入新的结点
     76 *
     77 * This is only for internal list manipulation where we know    //————————>只能用于操作已知prev和next指针的内部链表
     78 * the prev/next entries already!
     79 */
     80 static inline void __list_add(struct list_head *new,    //————————>__list_add:内联静态函数
     81                 struct list_head *prev,                    //————————>参数:三个指向list_head的结构体指针(新结点,前向结点,后向结点)
     82                 struct list_head *next)
     83 {
     84     next->prev = new;    //————————>双向链表中插入new结点
     85     new->next = next;
     86     new->prev = prev;
     87     prev->next = new;
     88 }
     89 
     90 /**
     91 * list_add – add a new entry    //————————>list_add:头插法增加新节点
     92 * @new: new entry to be added    //————————>new:新节点指针
     93 * @head: list head to add it after    //————————>head:链表头结点指针,在之后插入
     94 *
     95 * Insert a new entry after the specified head.    //————————>头插法
     96 * This is good for implementing stacks.    //————————>符合栈操作
     97 */
     98 static inline void list_add(struct list_head *new, struct list_head *head)    //————————>list_add:在head后面插入new
     99 {                                                                            //————————>new:新节点指针
    100     __list_add(new, head, head->next);                                        //————————>head:链表头结点指针
    101 }
    102 
    103 /**
    104 * list_add_tail – add a new entry    //————————>list_add_tail :尾插法增加新节点
    105 * @new: new entry to be added    //————————>new:新节点指针
    106 * @head: list head to add it beforer    //————————>head:链表头结点指针,在之前插入
    107 *
    108 * Insert a new entry before the specified head.
    109 * This is useful for implementing queues.    //————————>符合队列操作
    110 */
    111 static inline void list_add_tail(struct list_head *new, struct list_head *head)    //————————>list_add_tail :在head前面插入new
    112 {
    113     __list_add(new, head->prev, head);
    114 }
    115 
    116 
    117 
    118 //################ 链表删除算法 ################//
    119 /*
    120 * Delete a list entry by making the prev/next entries    //————————>通过改变prev和next的指向来删除节点
    121 * point to each other.
    122 *
    123 * This is only for internal list manipulation where we know    //————————>同样只能用于操作已知prev和next指针的内部链表
    124 * the prev/next entries already!
    125 */
    126 static inline void __list_del(struct list_head *prev, struct list_head *next)    //————————>__list_del:删除结点
    127 {                                                                                //————————>prev:待删除结点的前向指针
    128     next->prev = prev;                                                            //————————>next:待删除结点的后向指针
    129     prev->next = next;
    130 }
    131 
    132 /**
    133 * list_del – deletes entry from list.    //————————>list_del:删除节点
    134 * @entry: the element to delete from the list.    //————————>entry:要删除的结点
    135 * Note: list_empty on entry does not return true after this, the entry is in an undefined state.    //————————>操作后调用list_empty则返回随机值
    136 */
    137 static inline void list_del(struct list_head *entry)    //————————>删除entry结点
    138 {
    139     __list_del(entry->prev, entry->next);
    140     entry->next = (void *) 0;    //————————>置空
    141     entry->prev = (void *) 0;
    142 }
    143 
    144 /**
    145 * list_del_init – deletes entry from list and reinitialize it.    //————————>list_del_init:删除并初始化节点
    146 * @entry: the element to delete from the list.
    147 */
    148 static inline void list_del_init(struct list_head *entry)    //————————>删除并初始化entry指向的结点
    149 {
    150     __list_del(entry->prev, entry->next);    //————————>删除
    151     INIT_LIST_HEAD(entry);    //————————>然后初始化
    152 }
    153 
    154 
    155 
    156 //################ 链表移动算法 ################//
    157 /**
    158 * list_move – delete from one list and add as another’s head    //————————>list_move:从链表中删除一个节点并添加到另一个链表头部
    159 * @list: the entry to move    //————————>list:要移动的节点
    160 * @head: the head that will precede our entry    //————————>head:目标链表的头结点
    161 */
    162 static inline void list_move(struct list_head *list,    //————————>list_move:从链表中删除list并添加到head后面
    163                 struct list_head *head)
    164 {
    165     __list_del(list->prev, list->next);    //————————>先删除
    166     list_add(list, head);    //————————>然后在head后面添加list
    167 }
    168 
    169 /**
    170 * list_move_tail – delete from one list and add as another’s tail    //————————>list_move_tail:从链表中删除一个节点并添加到另一个链表尾部
    171 * @list: the entry to move
    172 * @head: the head that will follow our entry
    173 */
    174 static inline void list_move_tail(struct list_head *list,    //————————>list_move_tail:从链表中删除list并添加到head前部
    175                     struct list_head *head)
    176 {
    177     __list_del(list->prev, list->next);    //————————>先删除
    178     list_add_tail(list, head);    //————————>然后在head前面添加list
    179 }
    180 
    181 
    182 //################ 判断链表空状态 ################//
    183 /**
    184 * list_empty – tests whether a list is empty
    185 * @head: the list to test.
    186 */
    187 static inline int list_empty(struct list_head *head)    //————————>list_empty:判断head指向的链表是否为空
    188 {
    189     return head->next == head;    //————————>只有一个头结点
    190 }
    191 
    192 
    193 //################ 链表合并算法 ################//
    194 
    195 static inline void __list_splice(struct list_head *list,    //————————>__list_splice:将list链表合并到head链表上
    196                     struct list_head *head)
    197 {
    198     struct list_head *first = list->next;    //————————>list的首结点
    199     struct list_head *last = list->prev;    //————————>list的尾结点
    200     struct list_head *at = head->next;    //————————>head的首结点
    201                         //————————>将list所以结点链接到head的后面
    202     first->prev = head;    //————————>list首结点向前指向head
    203     head->next = first;    //————————>head向后指向list的首结点
    204 
    205     last->next = at;    //————————>list的尾结点向后指向head的首结点
    206     at->prev = last;    //————————>head的首结点向前指向list的尾结点
    207 }
    208 
    209 /**
    210 * list_splice – join two lists    //————————>list_splice:合并两个链表
    211 * @list: the new list to add.    //————————>list:要合并的链表
    212 * @head: the place to add it in the first list.    //————————>目标链表
    213 */
    214 static inline void list_splice(struct list_head *list, struct list_head *head)    //————————>list_splice:将list合并到head后面
    215 {
    216 if (!list_empty(list))    //————————>条件:list链表不为空
    217 __list_splice(list, head);
    218 }
    219 
    220 /**
    221 * list_splice_init – join two lists and reinitialise the emptied list.    //————————>list_splice_init:合并两个链表并重新初始化被链接的链表2013-7-30
    222 * @list: the new list to add.    //————————>list:要合并的链表
    223 * @head: the place to add it in the first list.    //————————>目标链表
    224 *
    225 * The list at @list is reinitialised    //————————>list:被重新初始化
    226 */
    227 static inline void list_splice_init(struct list_head *list,    //————————>list_splice_init:将list合并到head,并重新初始化list
    228 struct list_head *head)
    229 {
    230 if (!list_empty(list)) {    //————————>条件:list链表不为空
    231 __list_splice(list, head);
    232 INIT_LIST_HEAD(list);
    233 }
    234 }
    235 
    236 
    237 //################ 通过内部结构指针返回外部容器指针 ################//
    238 /**
    239 * list_entry – get the struct for this entry    //————————>list_entry:得到结点的外部结构地址
    240 * @ptr:    the &struct list_head pointer.    //————————>ptr:指向struct list_head类型链表的指针
    241 * @type:    the type of the struct this is embedded in.    //————————>type:包含结点的结构体类型
    242 * @member:    the name of the list_struct within the struct.    //————————>member:type结构中的结点类型
    243 */
    244 #define list_entry(ptr, type, member)                             //————————>list_entry:得到type结构的指针
    245 ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))    //————————>ptr:指向struct list_head类型链表的指针
    246                                                                 //————————>type:包含结点的结构体类型
    247                                                                 //————————>member:type结构中的结点类型
    248 
    249 
    250 
    251 //################ 链表遍历算法 ################//
    252 /**
    253 * list_for_each    -    iterate over a list    //————————>list_for_each:迭代一个链表
    254 * @pos:    the &struct list_head to use as a loop counter.    //————————>pos:循环计数器,struct list_head类型
    255 * @head:    the head for your list.    //————————>遍历链表头指针
    256 */
    257 #define list_for_each(pos, head)     //————————>list_for_each:利用for循环迭代head指向的链表
    258 for (pos = (head)->next; pos != (head); 
    259 pos = pos->next)    //————————>通过next指针逐项后移
    260 
    261 /**
    262 * list_for_each_prev    -    iterate over a list backwards    //————————>list_for_each_prev:反向迭代一个链表
    263 * @pos:    the &struct list_head to use as a loop counter.    //————————>pos:循环计数器,struct list_head类型
    264 * @head:    the head for your list.    //————————>遍历链表头指针
    265 */
    266 #define list_for_each_prev(pos, head)     //————————>list_for_each_prev:利用for循环反向迭代head指向的链表
    267 for (pos = (head)->prev; pos != (head); 
    268 pos = pos->prev)    //————————>也是通过next指针逐项后移
    269 
    270 /**
    271 * list_for_each_safe    -    iterate over a list safe against removal of list entry    //————————>list_for_each_safe:迭代一个链表
    272 * @pos:    the &struct list_head to use as a loop counter.
    273 * @n:        another &struct list_head to use as temporary storage    //————————>多用一个临时辅助变量进行迭代
    274 * @head:    the head for your list.
    275 */
    276 #define list_for_each_safe(pos, n, head) 
    277 for (pos = (head)->next, n = pos->next; pos != (head); 
    278 pos = n, n = pos->next)
    279 
    280 /**
    281 * list_for_each_entry    -    iterate over list of given type    //————————>list_for_each_entry:遍历链表中的内核链表容器结构
    282 * @pos:    the type * to use as a loop counter.    //————————>数据项结构指针类型,指向外部结构体
    283 * @head:    the head for your list.    //————————>遍历链表头指针
    284 * @member:    the name of the list_struct within the struct.    //————————>链表中结构成员的名字
    285 */
    286 #define list_for_each_entry(pos, head, member)                    //————————>list_for_each_entry:遍历head指向的链表的容器结构(外部结构体)
    287 for (pos = list_entry((head)->next, typeof(*pos), member);    
    288 &pos->member != (head);                     
    289 pos = list_entry(pos->member.next, typeof(*pos), member))    //————————>通过list_entry传入next来遍历外部结构
    290 
    291 /**
    292 * list_for_each_entry_safe – iterate over list of given type safe against removal of list entry    //————————>llist_for_each_entry_safe:遍历链表中的内核链表容器结构
    293 * @pos:    the type * to use as a loop counter.
    294 * @n:        another type * to use as temporary storage    //————————>多用一个临时辅助变量进行迭代
    295 * @head:    the head for your list.
    296 * @member:    the name of the list_struct within the struct.
    297 */
    298 #define list_for_each_entry_safe(pos, n, head, member)                //————————>list_for_each_entry_safe:遍历head指向的链表的容器结构(外部结构体)
    299 for (pos = list_entry((head)->next, typeof(*pos), member),    
    300 n = list_entry(pos->member.next, typeof(*pos), member);    
    301 &pos->member != (head);                     
    302 pos = n, n = list_entry(n->member.next, typeof(*n), member))
    303 
    304 #endif
    View Code
  • 相关阅读:
    中型PLC运控快速入门系列教程------第3节 编程语法样例讲解
    中型PLC运控快速入门系列教程------第2节 常用数据类型及变量介绍
    中型PLC运控快速入门系列教程------第1节 学习指南资料介绍
    Inoproshop入门系列教程-----第11节 中型PLC常用快捷方式介绍
    Inoproshop入门系列教程-----第10节 程序安全加密和解锁
    Inoproshop入门系列教程-----第9节 变量关联IO和掉电保持
    Inoproshop入门系列教程-----第8节 中型PLC固件升级方式
    Inoproshop入门系列教程-----第7节 库文件的安装及设备文件的导入
    Inoproshop入门系列教程-----第6节 通信等组态配置介绍
    Inoproshop入门系列教程-----第5节 流水灯样例快速编程上手
  • 原文地址:https://www.cnblogs.com/lcw/p/3224887.html
Copyright © 2020-2023  润新知