1. 程式人生 > >核心連結串列list.h檔案剖析

核心連結串列list.h檔案剖析

核心連結串列list.h檔案剖析

一、核心連結串列的結構【雙向迴圈連結串列】

    核心連結串列的好主要體現為兩點,1是可擴充套件性,2是封裝。可以將核心連結串列複用到使用者態程式設計中,以後在使用者態下程式設計就不需要寫一些關於連結串列的程式碼了,直接將核心中list.h中的程式碼拷貝過來用。

struct list_head
{
  struct list_head *next, *prev;
}; // 包含了兩個指向list_head結構體的指標next,prev[後驅和前驅]

二、核心連結串列常用介面

1、INIT_LIST_HEAD:建立連結串列

2、list_add:在prev和next之間插入結點

3、list_add_tail:在連結串列尾插入結點

4、list_del:刪除結點

5、list_entry:取出結點

6、list_for_each:遍歷連結串列

【推薦看使用sourceInsight檢視程式碼】

三、深入分析list.h

1offsetof【在已知某一個成員變數的名字和結構體型別的情況下,計算該成員相對於結構體的起始地址的偏移量】

#ifdef __compiler_offsetof
#define offsetof(TYPE,MEMBER)__compiler_offsetof(TYPE,MEMBER)
#else
#ifndef offsetof
#define offsetof(type, member) ((size_t) &((type*)0)->member)
#endif

2container_of【已知某一個成員變數的名字、指標和結構體型別的情況下,計算結構體的指標,也就是計算結構體的起始地址】

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

3LIST_HEAD_INIT【初始化一個結點名字為name的雙向迴圈連結串列的頭結點】

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

4LIST_HEAD【初始化一個結點名字為name的雙向迴圈連結串列的頭結點】

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

5INIT_LIST_HEAD【初始化連結串列節點,將next和prev指標都指向其自身,我們就構造了一個空的雙迴圈連結串列。】

static __INLINE__ void INIT_LIST_HEAD(struct list_head *list)
{
  list->next= list;
  list->prev= list;
}

6list_add【在頭結點後加一個新結點】

#ifndef CONFIG_DEBUG_LIST
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;
}
#else
extern void __list_add(struct list_head *new,
                       struct list_head *prev,
                       struct list_head *next);
#endif
 
static __INLINE__ void list_add(struct list_head *new,struct list_head *head)
{
 __list_add(new, head, head->next);
}

 

7list_add_tail【新增結點new到連結串列尾】

static __INLINE__ void list_add_tail(struct list_head *new, struct list_head *head)
{
 __list_add(new, head->prev, head);
} // 在head->prev和head之間加入new,即在連結串列尾加入new結點

8list_del【list_del將會將該節點與外界的“聯絡”切斷,然後就可以使用free釋放了(如果是核心態就用kfree或vfree)】

#define LIST_POISON1 0
#define LIST_POISON2 0
 
static __INLINE__ void __list_del(struct list_head *prev, struct list_head * next)
{
  next->prev= prev;
  prev->next= next;
}
 
#ifndef CONFIG_DEBUG_LIST
static __INLINE__ void list_del(struct list_head *entry)
{
 __list_del(entry->prev, entry->next);
  entry->next= LIST_POISON1;
  entry->prev= LIST_POISON2;
}
#else
extern void list_del(struct list_head *entry);
#endif

9list_replace【用結點new替換結點old

static __INLINE__ void list_replace(struct list_head *old,
                                    struct list_head *new)
{
  new->next =old->next;
 new->next->prev = new;
  new->prev =old->prev;
 new->prev->next = new;
}

10 list_replace_init【用結點new替換結點old,並初始化old

static __INLINE__ void list_replace_init(struct list_head *old,
    struct list_head *new)
{
 list_replace(old, new);
 INIT_LIST_HEAD(old);
}

11list_del_init【刪除結點entry,並初始化entry

static __INLINE__ void list_del_init(struct list_head*entry)
{
 __list_del(entry->prev, entry->next);
 INIT_LIST_HEAD(entry);
}

12list_move【先將list節點從原連結串列中刪除,然後將其新增到head連結串列的表頭】

static __INLINE__ void list_move(struct list_head *list, struct list_head *head)
{
 __list_del(list->prev, list->next);
  list_add(list,head);
}

13list_move_tail【先將list節點從原連結串列中刪除,然後將其新增到head連結串列的表尾】

static __INLINE__ void list_move_tail(struct list_head *list,
                                      struct list_head *head)
{
 __list_del(list->prev, list->next);
 list_add_tail(list, head);
}

14list_is_last【測試list節點是否為head連結串列的表尾節點。是返回1,否則返回0

static __INLINE__ int list_is_last(const struct list_head *list,
                                   const struct list_head *head)
{
  return list->next == head;
}

15list_empty【判斷head連結串列是否為空連結串列,是返回1,否則返回為0

static __INLINE__ int list_empty(const struct list_head *head)
{
  return head->next == head;
}


16list_empty_careful【判斷節點head的前驅和後驅是否都指向head。是返回1,否則返回0

static __INLINE__ int list_empty_careful(const structlist_head *head)
{
  struct list_head *next = head->next;
  return (next== head) && (next == head->prev);
}

17list_rotate_left【函式每次將頭結點後的一個結點放到head連結串列的末尾,直到head結點後沒有其他結點】

static __INLINE__ void list_rotate_left(struct list_head *head)
{
  struct list_head *first;
 
  if(!list_empty(head))
  {
    first =head->next;
   list_move_tail(first, head);
  }
}

18list_is_singular【判斷head連結串列是否為單節點連結串列。是返回1,否為0

static __INLINE__ int list_is_singular(const struct list_head *head)
{
  return !list_empty(head) && (head->next == head->prev);
}

19__list_cut_position【這個函式是將head連結串列的頭結點至entry節點之間的節點連在list節點後面,即組成以list節點為頭結點的新連結串列】

static __INLINE__ void __list_cut_position(struct list_head *list,
    struct list_head *head, struct list_head *entry)
{
  struct list_head *new_first = entry->next;
  list->next= head->next;
 list->next->prev = list;
  list->prev= entry;
  entry->next= list;
  head->next= new_first;
 new_first->prev = head;
}<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>

20list_cut_position【與__list_cut_position功能相似,不過要先判斷連結串列head是否為空連結串列,再判斷是否為了單鏈表而且節點不是entry的情況,如果head==entry,直接初始化list

static __INLINE__ void list_cut_position(struct list_head *list,
    struct list_head *head, struct list_head *entry)
{
  if(list_empty(head))
  {
    return;
  }
  if(list_is_singular(head) &&
     (head->next != entry && head != entry))
  {
    return;
  }
  if (entry ==head)
  {
   INIT_LIST_HEAD(list);
  }
  else
  {
   __list_cut_position(list, head, entry);
  }
}

21__list_splice【將list連結串列的全部節點(頭節點list除外)插入在prevnext節點之間】

static __INLINE__ void __list_splice(const struct list_head *list,
                                     struct list_head *prev,
                                     struct list_head *next)
{
  struct list_head *first = list->next;
  struct list_head *last = list->prev;
 
  first->prev= prev;
  prev->next= first;
 
  last->next= next;
  next->prev= last;
}

22list_splice_tail【在list是非空連結串列的情況下,將其插在head連結串列的尾部,即head節點的前面】

static __INLINE__ void list_splice_tail(struct list_head *list,
                                        struct list_head *head)
{
  if(!list_empty(list))
  {
   __list_splice(list, head->prev, head);
  }
}

23list_splice_init【在list是非空連結串列的情況下,將其插在head連結串列的尾部,即head節點的前面。然後對list節點進行初始化,排除不安全因素】

static __INLINE__ void list_splice_init(struct list_head *list,
                                        struct list_head *head)
{
  if(!list_empty(list))
  {
   __list_splice(list, head, head->next);
   INIT_LIST_HEAD(list);
  }
}

24list_splice_tail_init【在list是非空連結串列的情況下,將其插在head連結串列的尾部,即head節點的前面。然後對list節點進行初始化,排除不安全因素】

static __INLINE__ void list_splice_tail_init(struct list_head *list, struct list_head *head)
{
  if(!list_empty(list))
  {
   __list_splice(list, head->prev, head);
   INIT_LIST_HEAD(list);
  }
}

25list_entry【獲取type型別結構體的起始指標】

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

26list_first_entry【已知type型別的結構體中member成員的指標後,求得它所在的連結串列的下一個指標所指的member所在的type型別的結構體的起始地址】

#define list_first_entry(ptr, type, member) \
 list_entry((ptr)->next, type, member)

27list_for_each【從head節點開始(不包括head節點)遍歷它的每一個節點】

#define list_for_each(pos, head) \
  for (pos =(head)->next; prefetch(pos->next), pos != (head); \
          pos =pos->next)

28list_for_each_prev【它也是從head節點開始(不包括head節點)向前遍歷每一個節點!即從連結串列的尾部開始遍歷】

#define list_for_each_prev(pos, head) \
  for (pos =(head)->prev; prefetch(pos->prev), pos != (head); \
          pos =pos->prev)

29list_for_each_safe【從head節點開始(不包括head節點!)遍歷它的每一個節點!它用n先將下一個要遍歷的節點儲存起來,防止刪除本節點後,無法找到下一個節點,而出現錯誤】

#define list_for_each_safe(pos, n, head) \
  for (pos =(head)->next, n = pos->next; pos != (head); \
    pos = n, n =pos->next)

30list_for_each_prev_safe【它也是從head節點開始(不包括head節點)向前遍歷每一個節點!即從連結串列的尾部開始遍歷】

#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)

31list_for_each_entry【已知指向某個結構體的指標pos,以及指向它中member成員的指標head,從下一個結構體開始向後遍歷這個結構體鏈】

#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))

32list_for_each_entry_reverse【已知指向某個結構體的指標pos,以及指向它中member成員的指標head,從下一個結構體開始向前遍歷這個結構體鏈】

#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))

33list_prepare_entry【判斷pos這個指標是否為空,為空的話給它賦值list_entry(head, typeof(*pos), member)這條語句求出來的結構體的地址】

#define list_prepare_entry(pos, head, member) \
  ((pos) ? :list_entry(head, typeof(*pos), member))

34list_for_each_entry_continue【已知指向某個結構體的指標pos,以及指向它中的member成員的head指標,從它的下一個結構體開始向後遍歷這個連結串列】

#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))

35list_for_each_entry_continue_reverse【已知指向某個結構體的指標pos,以及指向它中的member成員的head指標,從它的前一個結構體開始向前遍歷這個連結串列】

#define list_for_each_entry_continue_reverse(pos,head, member)   \
  for (pos =list_entry(pos->member.prev, typeof(*pos), member);  \
      prefetch(pos->member.prev), &pos->member != (head);  \
       pos =list_entry(pos->member.prev, typeof(*pos), member))

36list_for_each_entry_from【從pos節點開始,向後遍歷連結串列】

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

37list_for_each_entry_safe【先儲存下一個要遍歷的節點!從head下一個節點向後遍歷連結串列】

#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))

38list_for_each_entry_safe_continue【先儲存下一個要遍歷的節點!從pos下一個節點向後遍歷連結串列】

#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))

39list_for_each_entry_safe_from【先儲存下一個要遍歷的節點!從pos節點向後遍歷連結串列】

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

40list_for_each_entry_safe_reverse【先儲存下一個要遍歷的節點!從連結串列尾部向前遍歷連結串列】

#define list_for_each_entry_safe_reverse(pos, n, head,member)    \
  for (pos =list_entry((head)->prev, typeof(*pos), member),  \
    n =list_entry(pos->member.prev, typeof(*pos), member); \
      &pos->member != (head);         \
       pos = n,n = list_entry(n->member.prev, typeof(*n), member))

41list_safe_reset_next【獲取n結構體指標】

#define list_safe_reset_next(pos, n, member)        \
  n =list_entry(pos->member.next, typeof(*pos), member)
// hash連結串列頭
struct hlist_head
{
  structh list_node *first;
};
 
struct hlist_node
{
  struct hlist_node *next, **pprev;
};

1INIT_HLIST_HEAD【初始化頭節點指標ptr

#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)

2INIT_HLIST_NODE【初始化hlist節點】

static __INLINE__ void INIT_HLIST_NODE(struct hlist_node *h)
{
  h->next =NULL;
  h->pprev =NULL;
}

3hlist_unhashed【判斷h->pprev是否為空,是返回1,否返回0

static __INLINE__ int hlist_unhashed(const struct hlist_node *h)
{
  return !h->pprev;
}

4hlist_empty【判斷hlist是否為空,是返回1,否返回0

static __INLINE__ int hlist_empty(const struct hlist_head *h)
{
  return !h->first;
}

5__hlist_del【刪除結點n

static __INLINE__ void __hlist_del(struct hlist_node*n)
{
  struct hlist_node *next = n->next;
  struct hlist_node **pprev = n->pprev;
  *pprev = next;
  if (next)
  {
   next->pprev = pprev;
  }
}

6hlist_del【刪除結點n,將結點nextpprev分別指向LIST_POISON1LIST_POISON2。這樣設定是為了保證不在連結串列中的結點項不能被訪問】

static __INLINE__ void hlist_del(struct hlist_node *n)
{
 __hlist_del(n);
  n->next =LIST_POISON1;
  n->pprev =LIST_POISON2;
}

7hlist_del_init【先判斷結點是否為空,不為空刪除,再初始化節點】

static __INLINE__ void hlist_del_init(struct hlist_node *n)
{
  if(!hlist_unhashed(n))
  {
   __hlist_del(n);
   INIT_HLIST_NODE(n);
  }
}

8hlist_add_head【增加結點nh表頭】

static __INLINE__ void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
{
  struct hlist_node *first = h->first;
  n->next =first;
  if (first)
  {
   first->pprev = &n->next;
  }
  h->first =n;
  n->pprev =&h->first;
}<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>

9hlist_add_before【增加結點n到結點next之前】

/* next must be != NULL */
static __INLINE__ void hlist_add_before(struct hlist_node *n,
                                        struct hlist_node *next)
{
  n->pprev =next->pprev;
  n->next = next;
  next->pprev= &n->next;
  *(n->pprev)= n;
}

10hlist_add_after【增加結點n到結點next之後】

static __INLINE__ void hlist_add_after(struct hlist_node *n,
                                       struct hlist_node *next)
{
  next->next= n->next;
  n->next =next;
  next->pprev= &n->next;
 
 if(next->next)
  {
   next->next->pprev  =&next->next;
  }
}

11hlist_move_list【頭結點new接管頭結點old的所有節點,並初始化old

static __INLINE__ void hlist_move_list(struct hlist_head *old,
                                       struct hlist_head *new)
{
  new->first= old->first;
  if(new->first)
  {
   new->first->pprev = &new->first;
  }
  old->first= NULL;
}

12hlist_entry【已知某一個成員變數的名字、指標和結構體型別的情況下,計算結構體的指標,也就是計算結構體的起始地址】

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

13hlist_for_each【遍歷hlist連結串列】

#define hlist_for_each(pos, head) \
  for (pos =(head)->first; pos ; \
       pos =pos->next)

14 hlist_for_each_safe【遍歷hlist連結串列,一般在刪除結點使用】

#define hlist_for_each_safe(pos, n, head) \
  for (pos =(head)->first; pos && ({ n = pos->next; 1; }); \
       pos = n)

15hlist_for_each_entry【遍歷找typeof(*tpos)的結構體型別入口地址】

#define hlist_for_each_entry(tpos, pos, head,member)      \
  for (pos =(head)->first;          \
       pos&& ({ prefetch(pos->next); 1;}) &&      \
    ({ tpos =hlist_entry(pos, typeof(*tpos), member); 1;}); \
       pos =pos->next)

16hlist_for_each_entry_continue【從結點pos下一個遍歷找typeof(*tpos)的結構體型別入口地址】

#define hlist_for_each_entry_continue(tpos, pos,member)     \
  for (pos =(pos)->next;            \
       pos&& ({ prefetch(pos->next); 1;}) &&      \
    ({ tpos =hlist_entry(pos, typeof(*tpos), member); 1;}); \
       pos =pos->next)

17hlist_for_each_entry_from【從節點pos開始遍歷找typeof(*tpos)的結構體型別入口地址】

#define hlist_for_each_entry_from(tpos, pos,member)       \
  for (; pos&& ({ prefetch(pos->next); 1;}) &&      \
    ({ tpos =hlist_entry(pos, typeof(*tpos), member); 1;}); \
       pos =pos->next)

18hlist_for_each_entry_safe【從頭節點head開始遍歷找typeof(*tpos)的結構體型別入口地址】

#define hlist_for_each_entry_safe(tpos, pos, n, head,member)      \
  for (pos =(head)->first;          \
       pos&& ({ n = pos->next; 1; }) &&         \
    ({ tpos =hlist_entry(pos, typeof(*tpos), member); 1;}); \
       pos = n)