2025-03-18
链表是一种常用的数据结构,在开发中经常会使用到。在Linux内核中同样也是一个很常用的数据结构,而且内核对链表实现了很多相关函数,极大方便了链表的使用。内核中的链表和一般的链表使用方法是不一样的。内核中的链表成员是结构体中的一个成员,通过内存偏移的方法,可以通过链表成员的内存地址得到宿主结构体成员的内存地址。
struct list_head {
struct list_head *next, *prev;
};
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) struct list_head name = LIST_HEAD_INIT(name)
// simple.c
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/slab.h>
struct data {
struct list_head list;
int num;
};
LIST_HEAD(my_list);
static int __init simple_init(void) {
pr_info("simple_init\n");
for (int i = 0; i < 3; i++) {
struct data *tmp = kmalloc(sizeof(struct data), GFP_KERNEL);
tmp->num = i;
list_add_tail(&tmp->list, &my_list);
}
struct list_head *ptr;
list_for_each_prev(ptr, &my_list) {
struct data *tmp = list_entry(ptr, struct data, list);
pr_info("num = %d\n", tmp->num);
}
struct data *tmp, *next;
list_for_each_entry_safe(tmp, next, &my_list, list) {
list_del(&tmp->list);
kfree(tmp);
}
return 0;
}
static void __exit simple_exit(void) { pr_info("simple_exit\n"); }
module_init(simple_init);
module_exit(simple_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("heng30");
MODULE_VERSION("v0.0.1");
MODULE_DESCRIPTION("A simple kernel module");
#!/bin/sh
top-dir = $(shell pwd)
kernel-version = $(shell uname -r)
kernel-dir ?= /lib/modules/$(kernel-version)/build
obj-m += simple.o
all:
make -C $(kernel-dir) modules M=$(top-dir)
clean:
rm -f *.o *.ko *.mod *.mod.c *.order *.symvers *.dtbo
make -C $(kernel-dir) clean m=$(top-dir)
编译程序:make
安装驱动:insmod simple.ko
移除驱动:rmmod simple.ko
查看输出:dmesg
[ 9806.982678] simple_init
[ 9806.982688] num = 2
[ 9806.982690] num = 1
[ 9806.982691] num = 0
[ 9815.804907] simple_exit