Linux内核链表 list_head学习笔记
kernel/inclue/linux/types.h
中定义的list_head
结构如下
struct list_head {
struct list_head *next, *prev;
};
//list_head为包含指针的结构体
Linux内核中的定义:
#define LIST_HEAD_INIT(name) { &(name), &(name) }
//括号内参数为地址/指针
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
//LIST_HEAD(name) 即为创建一个名为‘name’的list_head结构体,即链表头,pre和next指针都指向自己
static inline void INIT_LIST_HEAD(struct list_head *list)
{
WRITE_ONCE(list->next, list);
list->prev = list;
}
//已经创建了所需的结构体地址
```c
LIST_HEAD(name);
//等价于
struct list_head name = {&name, &name} ;
实际应用:list_head单独使用没有意义,需要再嵌套入结构体中,加入所需的可赋值变量
- 创建结构体:
struct birthday {
int day;
int month;
int year;
struct list_head list;
}
//嵌套了list_head的结构体birthday
先创建链表头
static LIST_HEAD(header);
创建首节点
- 方法一:
struct birthday me={
.day=22,
.month=8,
.2000,
.list=LIST_HEAD_INIT(me.list);
};
//#define LIST_HEAD_INIT(name) { &(name), &(name) }
//LIST_HEAD_INIT(name)代表一个大括号及其俩地址
而后将此节点插入header之后
list_add_tail(&me.list,&birthday.list);
- 方法二
struct birthday *me;
me.day=22;
me.month=8;
me.2000;
INIT_LIST_HEAD(&me.list);
//#define LIST_HEAD_INIT(name) { &(name), &(name) }
//LIST_HEAD_INIT(name)代表一个大括号及其俩地址
而后将此节点插入header之后
list_add_tail(&me.list,&birthday.list);
链表操作
- 插入节点
list_add
和list_add_tail
区别:
list_add(&me.list,&header) | list_add_tail(&me.list,&header) |
---|---|
list_add | list_add_tail |
在链表头head后方插入一个新节点 | 在链表头前方依次插入新的节点 |
- 删除节点
list_del(struct list_head *entry);
//删除链表中的任意节点
e.g.:
list_del(&me.list);
- 链表遍历(只是list_head的遍历)
内核中的遍历方式
从前向后遍历
#define list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
//从前向后遍历
从后向前遍历
#define list_for_each_prev(pos, head) \
for (pos = (head)->prev; pos != (head); pos = pos->prev)
//从后向前遍历
container_of(ptr, type, member)
//根据结构体重的一个成员变量地址导出包含这个成员变量member的struct地址
ptr | type | member |
---|---|---|
ptr : 成员变量mem的地址 | type: 包含成员变量mem的宿主结构体的类型 | member: 在宿主结构中的mem成员变量的名称 |
获取链表的首元素
list_first_entry(ptr, type, member)
// get the first element from a list
/**
* list_first_entry - get the first element from a list
* @ptr: the list head to take the element from.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_head within the struct.
*
* Note, that list is expected to be not empty.
*/
获取链表的next
list_next_entry(pos, member)
// get the next element from a list
/**
* list_next_entry - get the next element in list
* @pos: the type * to cursor(确定指针类型)
* @member: the name of the list_head within the struct.
*/
遍历结构体
list_for_each_entry(pos, head, member)
//pos只是用来typeof获得结构类型
#define list_for_each_entry(pos, head, member) \
for (pos = list_first_entry(head, typeof(*pos), member); \
&pos->member != (head); \
pos = list_next_entry(pos, member))
/**
* list_for_each_entry - iterate over list of given type
* @pos: the type * to use as a loop cursor.(确定指针类型)
* @head: the head for your list.
* @member: the name of the list_head within the struct.
*/
e.g.
struct birthday *ptr;
list_for_each_entry(ptr,&birthday_list,list)
{
printk ("val = %d\n" , ptr->val);
}
资料source:CSDN博主:风亦路 All Rights Reserved
万分感谢!