字符设备驱动高级篇1——新接口介绍

来源:互联网 发布:陕西广电网络集团待遇 编辑:程序博客网 时间:2024/06/04 18:57

以下内容源于朱有鹏《物联网大讲堂》课程的学习整理,如有侵权,请告知删除。


一、概览

1、新接口与老接口

(1)老接口:register_chrdev()

  • 通过第一个参数是否为0,判断内核是否自动分配设备号,或者就是该参数表示的设备号;
  • 此函数完成设备号分配,以及注册设备驱动的功能;

(2)新接口:register_chrdev_region() +cdev_add()

  • 先注册设备号,然后再注册设备驱动
  • 卸载时先卸载设备驱动,然后注销设备号。
  • register_chrdev_region()(传参表示要某个设备号),或者alloc_chrdev_region()(让内核自动分配设备号)。
  • cdev_add()(注册设备驱动)。

2、新接口涉及的内容

(1)cdev结构体


(2)设备号

  • 由主设备号和次设备号组成;
  • 属于dev_t类型(其实就是int类型);
  • MKDEV(由主次设备号得出设备号);
  • MAJOR(从设备号中提取主设备号);
  • MINOR(从设备号中提取次设备号);

(3)相关函数

  • cdev_alloc:分配空间
  • cdev_init:初始化
  • cdev_add:注册驱动
  • cdev_del:注销驱动

(3)总结

  • 使用register_chrdev_region (申请设备号)+ cdev_init(分配空间) + cdev_add(注册设备驱动)进行字符设备驱动注册;
  • 使用cdev_del(注销设备驱动)+unregister_chrdev_region(注销设备号)来注销字符设备驱动。
  • 即新接口将老接口的一步分为两步完成:申请设备号,然后注册设备驱动。


二、接口函数

1、register_chrdev_region函数申请想要的设备号

  • 此函数用来申请设备号(包括主次设备号);
  • 假如是 200(主设备号), 0 1 2 3(次设备号) ,则from为MKDEV(200,0)(MKDEV用来合成设备号,0表示起始次设备号),count为4(表示有四个次设备号);



2、alloc_chrdev_region函数自动分配设备号

  • register_chrdev_region,要事先知道所使用的主、次设备号,则要先用cat /proc/devices查看有没有使用。
  • 可以使用alloc_chrdev_region,让内核自动分配一个主设备号。
  • 如果申请成功,则把得到的设备号放入第一个参数dev中。

        


3、cdev_init函数              

  • 主要将cdev和fops关联起来。将传入的文件操作结构体指针赋值给cdev的ops
         
  • 可以不使用此函数,直接用下面的代码。
//cdev_init(pcdev, &test_fops);pcdev->owner = THIS_MODULE;pcdev->ops = &test_fops;


4、cdev_add函数

  • 此函数用来注册设备驱动。


5、cdev_alloc函数


(1)函数


(2)从内存角度体会cdev_alloc用与不用的差别
//static struct cdev test_cdev;//这个变量分配在数据段,整个程序运行期间都存在,不够灵活  static struct cdev *pcdev;   //只占4个字节,之后cdev_alloc给它实例化,分配在堆上,可以按需分配。由cdev_del释放  pcdev = cdev_alloc();  // 给pcdev分配内存,指针实例化

                                                                 

6、代码

(1)注册

  • 先注册主次设备号,然后才使用cdev_add()注册字符设备

        // 使用新的cdev接口来注册字符设备驱动,需要2步// 第1步:注册主次设备号mydev = MKDEV(MYMAJOR, 0);//MYMAJOR在这里是200,这里合成了要申请的设备号,即200,0retval = register_chrdev_region(mydev, MYCNT, MYNAME);//这里申请刚才合成的设备号if (retval) {printk(KERN_ERR "Unable to register minors for %s\n", MYNAME);return -EINVAL;}printk(KERN_INFO "register_chrdev_region success\n");// 第2步:注册字符设备驱动cdev_init(&test_cdev, &test_fops);//这步其实可以用其他代码来代替,见下节retval = cdev_add(&test_cdev, mydev, MYCNT);//注册字符设备驱动if (retval) {printk(KERN_ERR "Unable to cdev_add\n");return -EINVAL;}printk(KERN_INFO "cdev_add success\n");


(2)注销

        // 使用新的接口来注销字符设备驱动,注销分2步:// 第一步真正注销字符设备驱动用cdev_delcdev_del(&test_cdev);// 第二步去注销申请的主次设备号unregister_chrdev_region(mydev, MYCNT);


原创粉丝点击