zoukankan      html  css  js  c++  java
  • Linux设备驱动工程师之路——内核链表的使用【转】

    本文转载自:http://blog.csdn.net/forever_key/article/details/6798685

    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(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里面。

    二、实例

    [html] view plain copy
     
      1. #include <linux/kernel.h>  
      2. #include <linux/module.h>  
      3. #include <linux/init.h>  
      4. #include <linux/slab.h>  
      5. #include <linux/list.h>  
      6.    
      7. MODULE_LICENSE("GPL");  
      8. MODULE_AUTHOR("David Xie");  
      9. MODULE_DESCRIPTION("ListModule");  
      10. MODULE_ALIAS("List module");  
      11.    
      12. struct student  
      13. {  
      14.    char name[100];  
      15.    int num;  
      16.    struct list_head list;  
      17. };  
      18.    
      19. struct student *pstudent;  
      20. struct student *tmp_student;  
      21. struct list_head student_list;  
      22. struct list_head *pos;  
      23.    
      24. int mylist_init()  
      25. {  
      26.          inti = 0;  
      27.           
      28.          INIT_LIST_HEAD(&student_list);  
      29.           
      30.          pstudent= kmalloc(sizeof(struct student)*5,GFP_KERNEL);  
      31.          memset(pstudent,0,sizeof(structstudent)*5);  
      32.           
      33.          for(i=0;i<5;i++)  
      34.          {  
      35.                 sprintf(pstudent[i].name,"Student%d",i+1);  
      36.                    pstudent[i].num= i+1;  
      37.                    list_add(&(pstudent[i].list), &student_list);  
      38.          }  
      39.           
      40.           
      41.          list_for_each(pos,&student_list)  
      42.          {  
      43.                    tmp_student= list_entry(pos,struct student,list);  
      44.                    printk("<0>student%d name: %s ",tmp_student->num,tmp_student->name);  
      45.          }  
      46.           
      47.          return0;  
      48. }  
      49.    
      50.    
      51. void mylist_exit()  
      52. {         
      53.          inti ;  
      54.          for(i=0;i<5;i++)  
      55.          {  
      56.                    list_del(&(pstudent[i].list));      
      57.          }  
      58.           
      59.          kfree(pstudent);  
      60. }  
      61.    
      62. module_init(mylist_init);  
      63. module_exit(mylist_exit);  
  • 相关阅读:
    关于数据库的索引知识
    RESTful API设计相关
    Coroutine(协程)模式与线程
    Python网络编程中的服务器架构(负载均衡、单线程、多线程和同步、异步等)
    读懂diff
    Linux学习笔记——如何使用echo指令向文件写入内容
    ubuntu中执行定时任务crontab
    网络编程之异步IO,rabbitMQ笔记
    走进docker的世界之入门篇
    xml基础
  • 原文地址:https://www.cnblogs.com/zzb-Dream-90Time/p/6252375.html
Copyright © 2011-2022 走看看