一、重要知识点 1.内核链表和普通链表的区别内核链表是一个双向链表,但是与普通的双向链表又有所区别。内核链表中的链表元素不与特定类型相关,具有通用性。我们先来看一幅图 kernel list展示的是内核链表的结构,normallist展示的是普通链表的结构。head是链表头,p1,p2,p3是链表节点。从图中可以看出普通链表的p1的next指针是指向的结构体p2的地址,p2的pre指针指向p1结构体的地址。而内核链表的p1的next指向的是p2结构体中包含pre和next部分的地址,的p2的pre指向的是p1结构体中包含pre和next部分的地址。依此类推,这就是区别。内核结构元素不与特定类型结构相关,任何结构体都可通过内核的添加成为链表中的节点。2.内核链表的具体操作 链表数据结构的定义 structlist_head {struct list_head *next, *prev;
} 初始化链表头 INIT_LIST_HEAD(list_head*head) 插入节点 list_add(structlist_head *new, struct list_head *head) list_add_tail(structlist_head *new, sturct list_head *head)第一个函数在head后面插入一个节点第二个函数在链表尾部插入一个节点删除节点:list_del(structlist_head *entry)提取数据结构:list_entry(ptr,type, member)ptr为已知节点指针ptr,type为节点结构体类型,member为节点指针的type结构体中的名字。返回type结构体的指针。遍历:list for each(structlist_head *ops, struct list_head *head)从head开始遍历每个节点,节点指针保存在ops里面。二、实例
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/init.h>
- #include <linux/slab.h>
- #include <linux/list.h>
-
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("David Xie");
- MODULE_DESCRIPTION("ListModule");
- MODULE_ALIAS("List module");
-
- 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;
-
- int mylist_init()
- {
- inti = 0;
-
- INIT_LIST_HEAD(&student_list);
-
- pstudent= kmalloc(sizeof(struct student)*5,GFP_KERNEL);
- memset(pstudent,0,sizeof(structstudent)*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("<0>student%d name: %s
",tmp_student->num,tmp_student->name);
- }
-
- return0;
- }
-
-
- void mylist_exit()
- {
- inti ;
- for(i=0;i<5;i++)
- {
- list_del(&(pstudent[i].list));
- }
-
- kfree(pstudent);
- }
-
- module_init(mylist_init);
- module_exit(mylist_exit);