一、重要知识点
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
#include
#include
#include
#include
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\n”,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);