Linux设备驱动工程师之路——内核链表的使用

Linux设备驱动工程师之路——内核链表的使用

K-Style

转载请注明来自于衡阳师范学院08电2  K-Style  http://blog.csdn.net/ayangke,QQ:843308498 邮箱:yangkeemail@qq.com

 

一、重要知识点 

         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(struct list_head *new, struct list_head *head)

         list_add_tail(struct list_head *new, sturct list_head *head)

        第一个函数在head后面插入一个节点

        第二个函数在链表尾部插入一个节点

删除节点:

        list_del(struct list_head *entry)

提取数据结构:

        list_entry(ptr,type, member)

ptr为已知节点指针ptr,type为节点结构体类型,member为节点指针的type结构体中的名字。返回type结构体的指针。

遍历:

        list_for_each(struct list_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\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); 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值