介绍
需要头文件:<linux/list.h>
当使用链表接口时, 你应当一直记住列表函数不做加锁. 本文将介绍内核链表简单添、删、改、查操作。并附使用示例
1.链表初始化
初始化在list.h
中
struct list_head { struct list_head *next, *prev; };
自己申请链表
struct my_list
{
struct list_head list;
int priority; /* driver specific */
/* ... add other driver-specific fields */
};
列表的头常常是一个独立的 list_head 结构. 图链表头数据结构显示了这个简单的 struct list_head 是如何用来维护一个数据结构的列表的.
链表头必须在使用前用INIT_LIST_HEAD
宏来初始化.
struct my_list my_l;
INIT_LIST_HEAD(&my_l.list);
2.添加链表
2.1 添加链表头
static inline void list_add(struct list_head *new, struct list_head *head)
使用方法:
struct my_list new_node_01;
list_add(&new_node_01.list, &my_l.list);
2.2 添加链表尾
static inline void list_add_tail(struct list_head *new, struct list_head *head)
使用方法:
struct my_list new_node_02;
list_add_tail(&new_node_02.list, &my_l.list);
3.查询链表节点
3.1访问节点
通过遍历头节点,依次取出节点。需要注意:这个节点链表都是对struct list_head
类型进行遍历的,假设找到struct lis_head
,怎么去找到整个结构体,struct my_list
,通过如下实现
#define list_entry(ptr, type, member) \ container_of(ptr, type, member)
可以看list_entry源码,本质是container_of实现的,即通过成员变量的指针地址,来找到整个结构体的起始地址。
使用如下:
//假设找到的节点是cur_list,注意(cur_list 类型是struct list_head)
struct my_list *find_node = list_entry(cur_list, struct my_head, list);
其中:
- cur_list假设找到的节点
struct my_head
是要找整个节点的结构体- list 是整个结构体对应的名称。根据
struct my_list
中成员名字决定,可以设置为其他名称
3.2遍历整个节点
#define list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
其中:
- pos 相当于动态位置(struct list_head类型)
- head链表的节点(struct list_head类型)
使用方法:
struct my_list *find_node;
struct list_head *pos;
list_for_each(pos, new_node_01->list) {
// 通过当前成员名list的指针地址pos,来找到整个struct my_list结构体的起始地址
find_node = list_entry(pos, struct my_list, list);
}
3.删除链表节点
void list_del(struct list_head *entry);
即删除entry的节点
// 删除链表中的new_node_02节点
list_del(new_node_02.list);
样例子
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/list.h>
struct student{
char name[100];
int num;
struct list_head list;
};
struct student *pstudent;
struct student *tmp_student;
struct list_head student_list;
struct list_head *pos;
static __init int mylist_init(void){
int i=0;
printk(KERN_ERR"melvin function = %s\n", __func__);
INIT_LIST_HEAD(&student_list);
pstudent = kmalloc(sizeof(struct student) * 5, GFP_KERNEL);
memset(pstudent, 0, sizeof(struct student) * 5);
for(i = 0; i < 5; i++){
sprintf(pstudent[i].name, "student %d", i + 1);
pstudent[i].num = i + 1;
list_add(&(pstudent[i].list), &student_list);
}
list_for_each(pos, &student_list){
tmp_student = list_entry(pos, struct student, list);
printk(KERN_ERR"melvin student %d name :%s\n", tmp_student->num, tmp_student->name);
}
return 0;
}
static __exit void mylist_exit(void){
int i;
printk(KERN_ERR"melvin function = %s\n", __func__);
for(i=0; i < 5; i++){
list_del(&(pstudent[i].list));
}
kfree(pstudent);
}
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Melvin");
MODULE_DESCRIPTION("list module");
module_init(mylist_init);
module_exit(mylist_exit);