zoukankan      html  css  js  c++  java
  • Linux内核链表-通用链表的实现

      最近编程总想着参考一些有名的开源代码是如何实现的,因为要写链表就看了下linux内核中对链表的实现。

      链表是一种非常常见的数据结构,特别是在动态创建相应数据结构的情况下更是如此,然而在操作系统内核中,动态创建相应的数据结构尤为频繁。由于不带数据域所以Linux中的这种链表是通用的,在如何情况下,只要需要链表的数据结构包含它就行了。

      链表只包含两个指针 

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

      数据结构如果需要链表只需要包含它就行

    typedef struct s_DASTUC
    {
      int ds_stus;
      int ds_type;
      struct list_head ds_list;
      int ds_count;          
    }

      通过链表的地址获取链表所在的数据结构地址

    #define list_entry(ptr, type, number)    
                        ((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->number)))

    网上看到过有人说为什么不把链表放到数据结构首部,这样链表所在的地址就是数据结构的地址,何必实现list_entry(ptr, type, number),不要去限制数据结构调用链表的写法。

      详细的网上都有博客了,这里博主只是为了记下知识点而已,下面是从Linux源码List.h拿出来的部分实现:

      1 #ifndef _MYLIST_H
      2 #define _MYLIST_H
      3 
      4 #define LIST_POISON1    NULL
      5 #define LIST_POISON2    NULL
      6 
      7 /*
      8  * Simple doubly linked list implementation.
      9  *
     10  * Some of the internal functions ("__xxx") are useful when
     11  * manipulating whole lists rather than single entries, as
     12  * sometimes we already know the next/prev entries and we can
     13  * generate better code by using them directly rather than
     14  * using the generic single-entry routines.
     15  */
     16 
     17 struct list_head {
     18     struct list_head *next, *prev;
     19 };
     20 
     21 #define LIST_HEAD_INIT(name) { &(name), &(name) }
     22 
     23 #define LIST_HEAD(name) 
     24     struct list_head name = LIST_HEAD_INIT(name)
     25 
     26 static inline void INIT_LIST_HEAD(struct list_head *list)
     27 {
     28     list->next = list;
     29     list->prev = list;
     30 }
     31 
     32 /*
     33  * Insert a new entry between two known consecutive entries.
     34  *
     35  * This is only for internal list manipulation where we know
     36  * the prev/next entries already!
     37  */
     38 static inline void __list_add(struct list_head *new,
     39                   struct list_head *prev,
     40                   struct list_head *next)
     41 {
     42     next->prev = new;
     43     new->next = next;
     44     new->prev = prev;
     45     prev->next = new;
     46 }
     47 
     48 
     49 /**
     50  * list_add - add a new entry
     51  * @new: new entry to be added
     52  * @head: list head to add it after
     53  *
     54  * Insert a new entry after the specified head.
     55  * This is good for implementing stacks.
     56  */
     57 static inline void list_add(struct list_head *new, struct list_head *head)
     58 {
     59     __list_add(new, head, head->next);
     60 }
     61 
     62 
     63 
     64 /**
     65  * list_add_tail - add a new entry
     66  * @new: new entry to be added
     67  * @head: list head to add it before
     68  *
     69  * Insert a new entry before the specified head.
     70  * This is useful for implementing queues.
     71  */
     72 static inline void list_add_tail(struct list_head *new, struct list_head *head)
     73 {
     74     __list_add(new, head->prev, head);
     75 }
     76 
     77 /*
     78  * Delete a list entry by making the prev/next entries
     79  * point to each other.
     80  *
     81  * This is only for internal list manipulation where we know
     82  * the prev/next entries already!
     83  */
     84 static inline void __list_del(struct list_head * prev, struct list_head * next)
     85 {
     86     next->prev = prev;
     87     prev->next = next;
     88 }
     89 
     90 /**
     91  * list_del - deletes entry from list.
     92  * @entry: the element to delete from the list.
     93  * Note: list_empty() on entry does not return true after this, the entry is
     94  * in an undefined state.
     95  */
     96 static inline void list_del(struct list_head *entry)
     97 {
     98     __list_del(entry->prev, entry->next);
     99     entry->next = LIST_POISON1;
    100     entry->prev = LIST_POISON2;
    101 }
    102 
    103 /**
    104  * list_replace - replace old entry by new one
    105  * @old : the element to be replaced
    106  * @new : the new element to insert
    107  *
    108  * If @old was empty, it will be overwritten.
    109  */
    110 static inline void list_replace(struct list_head *old,
    111                 struct list_head *new)
    112 {
    113     new->next = old->next;
    114     new->next->prev = new;
    115     new->prev = old->prev;
    116     new->prev->next = new;
    117 }
    118 
    119 static inline void list_replace_init(struct list_head *old,
    120                     struct list_head *new)
    121 {
    122     list_replace(old, new);
    123     INIT_LIST_HEAD(old);
    124 }
    125 
    126 /**
    127  * list_del_init - deletes entry from list and reinitialize it.
    128  * @entry: the element to delete from the list.
    129  */
    130 static inline void list_del_init(struct list_head *entry)
    131 {
    132     __list_del(entry->prev, entry->next);
    133     INIT_LIST_HEAD(entry);
    134 }
    135 
    136 /**
    137  * list_move - delete from one list and add as another's head
    138  * @list: the entry to move
    139  * @head: the head that will precede our entry
    140  */
    141 static inline void list_move(struct list_head *list, struct list_head *head)
    142 {
    143     __list_del(list->prev, list->next);
    144     list_add(list, head);
    145 }
    146 
    147 /**
    148  * list_move_tail - delete from one list and add as another's tail
    149  * @list: the entry to move
    150  * @head: the head that will follow our entry
    151  */
    152 static inline void list_move_tail(struct list_head *list,
    153                   struct list_head *head)
    154 {
    155     __list_del(list->prev, list->next);
    156     list_add_tail(list, head);
    157 }
    158 
    159 /**
    160  * list_is_last - tests whether @list is the last entry in list @head
    161  * @list: the entry to test
    162  * @head: the head of the list
    163  */
    164 static inline int list_is_last(const struct list_head *list,
    165                 const struct list_head *head)
    166 {
    167     return list->next == head;
    168 }
    169 
    170 /**
    171  * list_empty - tests whether a list is empty
    172  * @head: the list to test.
    173  */
    174 static inline int list_empty(const struct list_head *head)
    175 {
    176     return head->next == head;
    177 }
    178 
    179 /**
    180  * list_empty_careful - tests whether a list is empty and not being modified
    181  * @head: the list to test
    182  *
    183  * Description:
    184  * tests whether a list is empty _and_ checks that no other CPU might be
    185  * in the process of modifying either member (next or prev)
    186  *
    187  * NOTE: using list_empty_careful() without synchronization
    188  * can only be safe if the only activity that can happen
    189  * to the list entry is list_del_init(). Eg. it cannot be used
    190  * if another CPU could re-list_add() it.
    191  */
    192 static inline int list_empty_careful(const struct list_head *head)
    193 {
    194     struct list_head *next = head->next;
    195     return (next == head) && (next == head->prev);
    196 }
    197 
    198 #define __list_for_each(pos, head) 
    199                     for (pos = (head)->next; pos != (head); pos = pos->next)
    200 
    201 #define list_first_entry(ptr, type, member) 
    202                     list_entry((ptr)->next, type, member)
    203 #define list_entry(ptr, type, number)    
    204                     ((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->number)))
    205 
    206 #endif
  • 相关阅读:
    vue.nextTick()方法简单理解
    vue中 hash和history的区别
    Set,Map一些常见的遍历方法以及转化方法
    vue中import和require的用法
    $route和 $router的区别是什么
    vue vmodel的总结
    vue router的钩子函数总结
    了解promise和async await的区别
    ZOJ 1642 Match for Bonus
    UVA 10003 Cutting Sticks
  • 原文地址:https://www.cnblogs.com/gt-xy/p/8029832.html
Copyright © 2011-2022 走看看