码迷,mamicode.com
首页 > 其他好文 > 详细

struct list_head结构体及相关函数

时间:2014-12-13 00:55:42      阅读:362      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   io   ar   color   os   使用   sp   

struct list_head结构体是linux实现数据结构双向链表的基础。其定义:

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

 可见链表里面的成员还是链表,每个链表都指向了前面和后面的链表。

一般将struct list_head作为一个成员,放到一个结构体中,其作用是可以从当前的结构体指针,获取到下一个链表元素的地址。一般用list_entry()来实现。具体按照下面的链接:

http://www.cnblogs.com/bastard/archive/2012/10/19/2731107.html

 

ok,下面来看看list_head为我们提供的一些接口:

先看一个基础的:

添加add:

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_head的next,一个是添加到prev。对应的函数分别为:list_add和list_add_tail.

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

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

如果不好理解的话,自己画个图,应该就能明白了。

 

删除delet:

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

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

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_init(struct list_head *entry)
{
 __list_del_entry(entry);
 INIT_LIST_HEAD(entry);
}

删除就是把某一节点从链表中删除。entry->next = LIST_POISON1; entry->prev = LIST_POISON2; LIST_POISON1/2在linux/poison.h中定义。删除后,为什么还要设置删除掉的节点指针呢?因为删除后,该选节点已不在链表当中,因此不会再使用。LIST_POISON1/2是两个不会存在于内核空间的地址,如果使用,就会报错。因此,设置指针,是强制禁用该节点。

inline void list_del_init 把entry从链表中delete,并将其初始化为一个空的链表。

替代replace:

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

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

 

移动move:

/**
 * list_move - delete from one list and add as another‘s head
 * @list: the entry to move
 * @head: the head that will precede our entry
 */
static inline void list_move(struct list_head *list, struct list_head *head)
{
 __list_del_entry(list);
 list_add(list, head);
}

/**
 * list_move_tail - delete from one list and add as another‘s tail
 * @list: the entry to move
 * @head: the head that will follow our entry
 */
static inline void list_move_tail(struct list_head *list,
      struct list_head *head)
{
 __list_del_entry(list);
 list_add_tail(list, head);
}

从原链表中删除,并添加到新的链表中。list_move添加到head后面,list_move_tail添加到head的前面。

 

//将head和它的next互换

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

 

/**
 * list_is_singular - tests whether a list has just one entry. //测试是否只有一个节点,除了头节点外。
 * @head: the list to test.
 */
static inline int list_is_singular(const struct list_head *head)
{
 return !list_empty(head) && (head->next == head->prev);
}

 

 链表一分为二cut:

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

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

注意这个是从entry处分开,list到entry为新的链表。head、entry->next、、、为老的链表。

举例:原来的链表是 head->1->2->3->4->5(只列出next方向,previous方向就是反过来),如果entry是2,那么新的链表是list->1->2,原来的链表则变为head->3->4->5。

看代码的一些小心得:一,阅读英文注释,不要害怕。二,静下心。

 

                        

 

struct list_head结构体及相关函数

标签:style   blog   http   io   ar   color   os   使用   sp   

原文地址:http://www.cnblogs.com/cyc2009/p/4160503.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!