Linux中实用链表介绍

1. 为使用链表机制, 你的驱动必须包含文件 <linux/list.h>. 其定义了list_head结构:

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

为使用Linux链表, 需要重新定义一个数据结构,结构中声明一个list_head类型的成员. 它的声明可能看起来象这样:
struct new_struct
{
  struct list_head list; /* 这个成员的位置无关,即可在结构中任意位置 */
  int data; /* 数据成员 */
  /* ... 添加其他字段 */
};

2. 链表在使用前必须初始化:
用宏INIT_LIST_HEAD来初始化
struct list_head new_list;
INIT_LIST_HEAD(&new_list);
或者直接用LIST_HEAD(new_list);

3. 函数/宏介绍:
list_add(struct list_head *new, struct list_head *head);
在链表头后添加一个新的节点。(可用来创建堆栈)

list_add_tail(struct list_head *new, struct list_head *head);
在链表头前添加一个新的节点。(可用来创建队列)

list_del(struct list_head *entry);
list_del_init(struct list_head *entry);
将给定的节点从链表中删除. 如果入口项可能注册在另外的链表中, 你应当使用 list_del_init, 它重新初始化这个链表指针.

list_move(struct list_head *entry, struct list_head *head);
list_move_tail(struct list_head *entry, struct list_head *head);
将给定的入口项从它当前的链表里去除并且增加到 head 的开始. 为安放入口项在新链表的末尾, 使用 list_move_tail 代替.

list_empty(struct list_head *head);
如果给定链表是空, 返回一个非零值.

list_splice(struct list_head *list, struct list_head *head);
将 list 紧接在 head 之后来连接 2 个链表.

list_entry(struct list_head *ptr, type_of_struct, field_name);
根据struct list_head指针获取其对应的节点。
这里ptr是一个指向使用的struct list_head的指针, type_of_struct是包含ptr的结构的类型, field_name是结构中链表成员的名字.

list_for_each(struct list_head *cursor, struct list_head *list)
这个宏创建一个for循环, 执行一次, cursor指向链表中的每个连续的入口项. 小心改变链表在遍历它时.

void new_add_entry(struct new_struct *new)
{
  struct list_head *ptr;
  struct new_struct *entry;

  list_for_each(ptr, &new_list)
  {
    entry = list_entry(ptr, struct new_struct, list);
    list_add_tail(&new->list, ptr);
    return;
  }
  list_add_tail(&new->list, &new_struct)

}

4.其他几个宏:
list_for_each_prev(struct list_head *cursor, struct list_head *list)
这个版本后向遍历链表.

list_for_each_safe(struct list_head *cursor, struct list_head *next, struct list_head *list)
如果你的循环可能删除列表中的项, 使用这个版本. 它简单的存储列表 next 中下一个项, 在循环的开始, 因此如果 cursor 指向的入口项被删除, 它不会被搞乱.

list_for_each_entry(type *cursor, struct list_head *list, member)
list_for_each_entry_safe(type *cursor, type *next, struct list_head *list, member)
这些宏定义减轻了对一个包含给定结构类型的列表的处理.
这里, cursor是一个指向包含数据类型的指针, member是包含结构中 list_head 结构的名子.
有了这些宏, 没有必要安放 list_entry 调用在循环里了.

 

 

posted on 2013-07-11 14:33  eric.geoffrey  阅读(171)  评论(0编辑  收藏  举报

导航