美文网首页Linux驱动
L1. 内核驱动注册流程

L1. 内核驱动注册流程

作者: 拂去尘世尘 | 来源:发表于2020-06-15 10:56 被阅读0次

    1.申请设备号

           驱动结构体填充完毕后,需要注册到内核之中,其中有三种方法来注册设备驱动:

    (1) 动态注册申请设备号 + cdev  注册设备驱动

           在不知道设备号的情况下,通过动态注册驱动申请到的设备号并存到dev_t 类型中,通过cdev_init将驱动结构体ops赋值给cdev->ops,然后通过cdev_add将cdev结构体与设备号关联。

    动态注册并申请设备号API:

        alloc_chrdev_region(dev_t*dev, unsigned baseminor, unsigned count, constchar *name)

        dev:               alloc_chrdev_region函数向内核申请下来的设备号结构体

        baseminor :   次设备号的起始

        count:            申请次设备号的个数

        name :           执行cat /proc/devices显示的名称

    cdev的使用:

        a. 执行cdev_init函数,将cdev和file_operations关联起来

        b. 使用cdev_add函数,将cdev和设备号关联起来

    卸载API:

        unregister_chrdev_region(dev *dev, int num);

    eg:  

        驱动动态设备号注册实例:  flashlight_devno为被赋值的结构体变量

    1.1 动态注册

        cdev_init原型

    1.2 cdev_init原型

        cdev_add原型

    1.3 cdev_add原型

        cdev卸载API: void cdev_del(structcdev *p)

    (2) 静态申请设备号 + cdev 注册设备驱动

        在已知驱动主设备号的情况下,可以通过静态注册驱动。其步骤与动态注册有些区别。需要先定义一个dev_t结构体,然后通过MKDEV将主设备号与此设备号合成赋值给dev_t。

    静态注册驱动API:

        int register_chrdev_region(dev_t*dev, unsigned int count, char *name);

        dev: 由已知的主设备号合成的设备号结构体MKDEV(major,mnior)的返回值

        count: 申请此设备号个数

        name: 设备名 出现在/proc/devices

    卸载静态注册API:

        unregister_chrdev_region(dev *dev, int num);

    eg.静态注册获取设备号,其中major为已经被赋值的变量

    1.4 静态注册驱动

    (3) 自动识别静态、动态分配

        程序也可以自动选择静态或动态分配API:

        int register_chrdev(unsigned int num, const char *name,struct file_operations *ops)

        num:为0时动态注册,非零时以num为主设备号静态注册。

        Name:设备名

        ops: 驱动结构体

    卸载API:int unregister_chrdev(unsigned int major, const  char *name)

        与上两个注册方法不同的是,int register_chrdev会自动将ops与设备号关联,不用手动cdev_init、cdev_add。且当创建class节点需要设备号结构体时,需要MKDEV(major,minor)返回值。但是此API较为耗资源。

    eg.自动识别静态、动态分配

    1.5 自动识别注册

    根据主次设备号获取设备号结构体API:

        dev_num=MKDEV(major,minor);  major是一个表示设备号的主设备号,minor次设备号

    根据设备号结构体获取主次设备号API:

        major = MAJOR(dev_num); 获取主设备号

        minor = MINOR(dev_num); 获取从设备号

        设备注册成功后,在/pro/device可查看

    2.创建节点

        设备注册进去后,需要创建节点才可以使驱动被调用。

        在/sys/class创建节点类API:

        struct class *class_create(structmodule *owner, const char *name)

        owner:模块所有者

        name: 指定类名   //在/sys/下可见

        在/sys/class/name已知类节点下创建设备节点API:

        struct device *device_create(struct class*cls, struct device *parent, dev_t devt, void *drvdata,const char *fmt, ...);

        eg.创建节点

    2.1 创建节点

        注意:/sys/class/xx/device与/dev/device区别(xx表示设备类名,device表示设备名)

        在驱动注册成功后,需要软件创建设备节点。在设备节点创建成功后,内核就会在/dev/下生成设备名。其中/dev/下存的是真实的设备,/sys/class/xx/存的是设备节点名,反映驱动设备的层次。调用驱动时需要将/dev下的设备作为路径,也可以通过设备节点名再下一级的节点传参。即”/sys/class/xx/device”不能作为调用路径,”/dev/device”可以作为调用路径。

    相关文章

      网友评论

        本文标题:L1. 内核驱动注册流程

        本文链接:https://www.haomeiwen.com/subject/vplcxktx.html