基本结构:
struct list_head{
struct list_head *next,*prev;
};
结构体定义于kernel/include/linux/types.h,该结构体只有2个元素,指向struct list_head 同类型的指针。
next指向链表下一个元素,prev指向链表上一个元素。
常用接口定义在list.h目录。
该结构体一般不单独使用,而是当多个资源需要组成链表时,加入该变量,充当结构体的链表区。
举例:
struct frame {
struct list_head list;
u32 tag;
ktime_t sent; /* high-res time packet was sent */
ulong waited;
ulong waited_total;
struct aoetgt t; / parent target I belong to */
…
char flags;
};
上面结构体中,list变量充当链表区,其他变量属于数据区,
把list插入链表,实际上就相当于把整个结构体插入了链表,找到list,也就找到整个结构体了。
常用接口:
1、定义struct list_head 类型的变量:
①常规定义:struct list_head my_list;
该方法定义的变量,在使用前需要调用 INIT_LIST_HEAD宏进行初始化。
②采用linux提供的接口:LIST_HEAD(my_list);
定义的同时会自动初始化,可直接使用
2、插入
①list_add(struct list_head * new,struct list_head *head)
在指针head位置插入元素new
②list_add_tail(struct list_head *,struct list_head *head)
在链表的尾部插入元素new,如果head本身为空链表,则于list_add执行动作一样。
3、将链表元素从其所在的链表上删除
①list_del(stuct list_head * entry)
该函数有2个功能,1,把该元素的首位元素重新连接,构成新的链表。
2,该元素的next,prev指针指向固定的地址(不是指空)。
②list_move(struct list_head *list,struct list_head * head)
把list从其原来的链表上删除,再插入head所指的链表头部
③list_move_tail(struct list_head *list,struct list_head *head)
把list从其原来的链表上删除,再插入head所指的链表尾部
④static inline int list_is_last(const struct list_head *list,
const struct list_head *head)
{
return list->next == head;
}
检查list是否是链表上最后一个元素。该链表是双链表,所以链表头head的prev指向尾部元素,尾部元素的next指向head,
如果list->next == head,证明是最后一个元素。
⑤static inline int list_empty(const struct list_head *head)
{
return READ_ONCE(head->next) == head;
}
检查head链表是否为空
3、跟数据段有关的API
例子:
struct frame {
struct list_head list;
u32 tag;
ktime_t sent; /* high-res time packet was sent */
ulong waited;
ulong waited_total;
struct aoetgt t; / parent target I belong to */
…
char flags;
};