#include <linux/module.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/slab.h>
static char* list_str = "default";
module_param(list_str, charp, 0644);
MODULE_PARM_DESC(list_str, "A list string");
static int list_count = 0;
module_param(list_count, int, 0644);
MODULE_PARM_DESC(list_count, "A list count");
static char* add_list_str[16];
int add_list_count;
module_param_array(add_list_str, charp, &add_list_count, 0644);
MODULE_PARM_DESC(add_list_str, "A char* array");
struct my_student
{
struct list_head list;
spinlock_t lock;
struct work_struct my_student_work;
};
struct my_student_list
{
struct list_head list;
int id;
char name[16];
};
static struct my_student stu;
void print_student(struct my_student_list *stu_list)
{
printk (KERN_ALERT "======================\n");
printk (KERN_ALERT "id =%d\n", stu_list->id);
printk (KERN_ALERT "name=%s\n", stu_list->name);
printk (KERN_ALERT "======================\n");
}
#if 0 // list_for_each_entry, list_del
static void my_student_work_fun_del(struct work_struct *work)
{
unsigned long flags;
//add student
printk(KERN_ALERT "**********START***************\n");
printk(KERN_ALERT "%s\n", __func__);
struct my_student *local_stu = container_of(work, struct my_student, my_student_work);
printk(KERN_ALERT "**********%p, %p***************\n", &stu, local_stu);
spin_lock_irqsave(&stu.lock, flags);
while (!list_empty(&stu.list)) {
struct list_head *next;
struct my_student_list *local_stu_list;
next = local_stu->list.next;
local_stu_list = list_entry(next, struct my_student_list, list);
print_student(local_stu_list);
list_del(&local_stu_list->list);
}
spin_unlock_irqrestore(&stu.lock, flags);
printk(KERN_ALERT "*********END****************\n");
}
#endif
// // list_entry, list_del
static void my_student_work_fun(struct work_struct *work)
{
unsigned long flags;
int i;
//add student
printk(KERN_ALERT "**********START***************\n");
printk(KERN_ALERT "%s\n", __func__);
struct my_student *local_stu = container_of(work, struct my_student, my_student_work);
printk(KERN_ALERT "**********%p, %p***************\n", &stu, local_stu);
spin_lock_irqsave(&stu.lock, flags);
if (!list_empty(&local_stu->list)) {
struct my_student_list *local_stu_list;
list_for_each_entry(local_stu_list, &local_stu->list, list) {
print_student(local_stu_list);
}
}
spin_unlock_irqrestore(&stu.lock, flags);
printk(KERN_ALERT "*********END****************\n");
}
int linked_list_init(void)
{
unsigned long flags;
char name[16] = {0};
int count;
printk(KERN_ALERT "*************************\n");
printk(KERN_ALERT "%s\n", __func__);
printk(KERN_ALERT "list_count %d.\n", list_count);
printk(KERN_ALERT "list_str %s.\n", list_str);
spin_lock_init(&stu.lock);
INIT_LIST_HEAD(&stu.list);
INIT_WORK(&stu.my_student_work, my_student_work_fun);
spin_lock_irqsave(&stu.lock, flags);
// add str 1
for (count = 0; count < list_count; count++) {
// add TJG
struct my_student_list *list;
list = kmalloc(sizeof(*list), GFP_KERNEL); //GFP_KERNEL, GFP_ATOMIC
if (list == NULL) {
return -ENOMEM;
}
list->id = count;
sprintf(name, "TJG%d", count);
memcpy(list->name, name, strlen(name));
list_add_tail(&list->list, &stu.list);
}
// add str 2
for (count = 0; count < add_list_count; count++) {
// add TJG
struct my_student_list *list;
list = kmalloc(sizeof(*list), GFP_KERNEL); //GFP_KERNEL, GFP_ATOMIC
if (list == NULL) {
return -ENOMEM;
}
list->id = count;
memcpy(list->name, add_list_str[count], strlen(name));
list_add_tail(&list->list, &stu.list);
}
spin_unlock_irqrestore(&stu.lock, flags);
printk(KERN_ALERT "*********end*************%p***\n", &stu);
schedule_work(&stu.my_student_work);
return 0;
}
void linked_list_exit(void)
{
printk(KERN_ALERT "*************************\n");
printk(KERN_ALERT "%s\n", __func__);
printk(KERN_ALERT "*************************\n");
}
module_init(linked_list_init);
module_exit(linked_list_exit);
MODULE_AUTHOR("TJG ");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Linked list test");
测试命令:
sudo insmod linked-list.ko add_list_str="aaa","bbb","ccc","ddd" list_count=5
测试log:
[14130.055619] *************************
[14130.055622] linked_list_init
[14130.055623] list_count 5.
[14130.055623] list_str default.
[14130.055627] *********end*************000000001dd5dc6d***
[14130.055633] **********START***************
[14130.055634] my_student_work_fun
[14130.055635] **********000000001dd5dc6d, 000000001dd5dc6d***************
[14130.055636] ======================
[14130.055636] id =0
[14130.055637] name=TJG0
[14130.055638] ======================
[14130.055638] ======================
[14130.055639] id =1
[14130.055640] name=TJG1
[14130.055641] ======================
[14130.055641] ======================
[14130.055642] id =2
[14130.055643] name=TJG2
[14130.055644] ======================
[14130.055645] ======================
[14130.055645] id =3
[14130.055646] name=TJG3
[14130.055647] ======================
[14130.055647] ======================
[14130.055648] id =4
[14130.055649] name=TJG4
[14130.055649] ======================
[14130.055650] ======================
[14130.055650] id =0
[14130.055651] name=aaa
[14130.055652] ======================
[14130.055653] ======================
[14130.055653] id =1
[14130.055654] name=bbb
[14130.055655] ======================
[14130.055656] ======================
[14130.055656] id =2
[14130.055657] name=ccc
[14130.055658] ======================
[14130.055658] ======================
[14130.055659] id =3
[14130.055659] name=ddd
[14130.055660] ======================
[14130.055660] *********END****************