基本知识可以看这个网址 深入分析 Linux 内核链表http://www.ibm.com/developerworks/cn/linux/kernel/l-chain/ 这个例子包括简单的增、删、遍历#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("List Module"); 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(void) { int i = 0; //初始化一个链表,其实就是把student_list的prev和next指向自身 INIT_LIST_HEAD(&student_list); pstudent = kmalloc(sizeof(struct student)*5,GFP_KERNEL);//向内核申请5个student结构空间 memset(pstudent,0,sizeof(struct student)*5); //清空,这两个函数可以由kzalloc单独做到 for(i=0;i<5;i++) { //为结构体属性赋值 sprintf(pstudent[i].name,"Student%d",i+1); pstudent[i].num = i+1; //加入链表节点,list_add的话是在表头插入,list_add_tail是在表尾插入 list_add( &(pstudent[i].list), &student_list);//参数1是要插入的节点地址,参数2是链表头地址 } list_for_each(pos,&student_list) //list_for_each用来遍历链表,这是个宏定义 //pos在上面有定义 { //list_entry用来提取出内核链表节点对应的实际结构节点,即根据struct list_head来提取struct student //第三个参数list就是student结构定义里的属性list //list_entry的原理有点复杂,也是linux内核的一个经典实现,这个在上面那篇链接文章里也有讲解 tmp_student = list_entry(pos,struct student,list); //打印一些信息,以备验证结果 printk("<0>student %d name: %s/n",tmp_student->num,tmp_student->name); } return 0; } void mylist_exit(void) { int i ; /* 实验:将for换成list_for_each来遍历删除结点,观察要发生的现象,并考虑解决办法 */ for(i=0;i<5;i++) { //额,删除节点,只要传个内核链表节点就行了 list_del(&(pstudent[i].list)); } //释放空间 kfree(pstudent); } module_init(mylist_init); module_exit(mylist_exit);