• 【linux驱动开发】-字符设备驱动高级


    1.注册字符设备驱动新接口

            在字符设备驱动基础章节,我们使用的注册字符设备驱动的接口为register_chrdev,在本章节我们要学习一种注册字符设备驱动的新接口register_chrdev_region/alloc_chrdev_region+cdev

    因为内核一直在更新,新老设备注册的驱动都有!

    在使用新接口注册字符设备驱动的过程中,我们首先要了cdev结构体相关的函数和设备号相关的概念!

    使用register_chrdev_region+cdev_init+cdev_add注册

    cdev结构体相关的函数有cdev_alloc、cdev_init、cdev_add、cdev_del

    dev_t类型中,有需要用到的三个宏,MKDEV(用主设备号和次设备号算出来一个主次设备号)、MAJOR(从主次设备号里提取得到主设备号)、MINOR(从主次设备号里提取得到从设备号)

    在驱动开头定义static struct cdev test_cdev(cdev结构体)、static dev_t  mydev(dev_t  型设备号)

    1. /*省略头文件、file_operation结构体、以及动作函数 只保留注册卸载函数*/
    2. #define MYCNT 1;
    3. #define MYMAJOR 200;
    4. static struct cdev test_cdev;
    5. static dev_t mydev;
    6. static int__init chrdev_init(void)
    7. {
    8. int ret;
    9. /*
    10. 使用新的cdev的接口来注册字符设备驱动
    11. 新的接口注册设备驱动需要两步
    12. */
    13. /*第一步:注册字符设备、分配主次设备号*/
    14. mydev=MKDEV(MYMAJOR,0);//主设备号为200,次设备号为0
    15. ret=register_chrdev_region(mydev,MYCNT,MYNAME);//使用此函数事先必须知道设备号,MYNAME设
    16. // 备名字
    17. if(ret)
    18. {
    19. printk(KERN_ERR"unable to register minors for%s\n",MYNAME);
    20. return -EINVAL;
    21. }
    22. printk(KERN_ERR"register_chrdev_region success\n");
    23. printk(KERN_ERR"major=%d\n minor=%d\n",MAJOR(mydev),MINOR(mydev));
    24. /*通过最后一个函数打印出来我们的主设备号、从设备号*/
    25. /*静态初始化字符设备*/
    26. cedv_init(&test_cdev,&test_fops);
    27. ret=cdev_add(&test_cdev,mydev,MYCNT);//把字符添加到系统中去
    28. if(ret)
    29. {
    30. printk(KERN_ERR"unable to cdev_add\n");
    31. return -EINVAL;
    32. }
    33. printk(KERN_ERR"cdev_add success\n");
    34. }
    35. static void__exit chrdev_exit(void)
    36. {
    37. /*第一步:真正的去注销字符设备驱动用cdev_del*/
    38. cedv_del(&test_cdev);
    39. /*第二步:去注销申请的主次设备号*/
    40. unregister_chrdev_region(mydev,MYCNT);
    41. }

    使用register_chrdev_region+cdev_init+cdev_add注册设备驱动,是事先要知道使用的主次设备号时使用的;要先查看cat/proc/devices去查看没有使用的;

    更简单、更智能的方法是让内核给我们自动分配一个主设备号!那alloc_chrdev_region就可以实现了!

    使用alloc_chrdev_region+cdev_init+cdev_add注册

    如上图所示,利用alloc_chrdev_region注册设备,只用改动上述程序的标记部分,因为主设备号是自动分配的,所以就没必要去宏定义主设备号,次设备号一般是从0开始,但不限于从0开始

    使用cdev_alloc

    注释掉上面这个cdev的结构体,转而用ststic struct cedv *pdev的结构体指针代替!

     

     如此一来,后面使用到cdev结构体相关的test_cdev地址问题都可以用pdev代替!

    在使用cdev_init之前,必须调用cdev_alloc()给我们定义的结构体指针pdev申请内存!

    pdev=cdev_alloc();给pdev分配内存,指针实例化,调用了内核中的kmalloc等的函数!其他部分不用变,实现的跟上面程序一样的功能!

    除此之外,在补充个知识点,为什么说这个呢?就是在分析内核的时候,知道有这两个写法!

     自动创建字符设备驱动的设备文件

           在字符设备基础笔记中,我们知道在向内核注册成功一个字符设备驱动以后,我们是使用mknod命令在/dev目录下生成一个设备文件节点,然后应用层通过这个设备节点进行调用驱动里面的一些动作函数,mknod命令每次都要手动操作实现,这个小节我们讨论如何能让系统自动生成驱动的设备文件!

    解决方案:udev(嵌入式中用的是mdev)!

    什么是udev:应用层的一个应用程序,是BusyBox中的一个命令,内核源码是找不到的。内核驱动和应用层udev之间有一套信息传输机制(netlink协议),应用层启动udev,内核驱动中使用相应接口。驱动注册和注销时信息会被传给udev,由udev在应用层进行设备文件的创建和删除!

    内核驱动设备类相关的函数以及使用

    class_create 、 device_create   //创建函数

    device_destory()、class_destory()  //销毁函数

    这两个函数目的就是发信息给udev,让udev赶紧创建设备文件!

    1. /*此处省略注册函数主体*/
    2. /*注册字符设备驱动完成后,添加设备类的操作,让内核发信息给udev,让udev自动删除和创建设备文件*/
    3. test_class=class_creat(THIS_MODULE,"aston_class");//参数2是类名要和app文件中设备名字保持一致
    4. //参数1是固定宏,不用动
    5. if(IS_ERR(test_class))
    6. return -EINVAL;
    7. //最后一个参数就是希望在应用中创建的设备文件的名字,是/dev/aston_test
    8. device_creat(test_class,NULL,mydev,NULL,"aston_test");
    9. /*下面的程序是写在卸载函数中的,当驱动卸载后,自动删除设备文件*/
    10. device_destory(test_class,mydev);
    11. class_destory(test_class);

    然后就在app中修改这个设备文件就可以了,    #define FILE "aston_test"

    关于设备类

    /pros/ /sys/ 这两个都是虚拟的文件系统。写或读这个文件就相当于在读写内核中的一些数据结构。

    这些文件系统中有一些设备类,就是按照不同设备驱动的特性去归类,方便我们进行管控。

    比如刚才,我们通过class_create建立了一个aston_class的类,我们通过cd/sys/class/就可看到

     然后cd/aston_class 就可以看到aton_test这个设备文件,再进一步,进入到aton_tests

     可以看到,在这个文件里面,有uevent文件,这些文件是内核中自动组织的文件。我们再进一步,查看一下uevent文件。cat uevent!

    class文件夹中的每一个文件都是一个类,uevent及class就是内核提供给我们的一个和内核进行交互的一个窗口,通过这个class,我们就可以了解驱动程序安装卸载等过程中内核所发生的事情。

  • 相关阅读:
    Go语言循环语句
    springboot集成canal实现同步双写
    基于SpringBoot的企业客户管理系统
    分布式集群理论
    C#(二十八)之C#鼠标事件、键盘事件
    【微信小程序】数字化会议OA系统之投票模块(附源码)
    归并排序(10分)
    Broker消息设计--Kafka从入门到精通(十三)
    【学习笔记】开源计算机视觉库OPENCV学习方案
    ASPX与ASP URL传递值问题
  • 原文地址:https://blog.csdn.net/weixin_49176627/article/details/126334553