码迷,mamicode.com
首页 > 系统相关 > 详细

Linux 驱动框架---linux 驱动

时间:2020-09-17 13:59:46      阅读:41      评论:0      收藏:0      [点我收藏+]

标签:const   内存   devices   私有   init   意义   分配   源码   uil   

  总述    

     Linux 系统下的驱动最后都是以如下这个结构体呈现在系统中的,注意其中的dev_pm_ops增加来准备替换platform_driver中的电源管理相关的内容的。这里内容主要都是流程梳理的没有详细罗列具体的Linux内核代码的内容所以可以参考源码来学习。也可以看文末的参考博客写的比较傲详细。

struct device_driver {
    const char        *name;
    struct bus_type        *bus;  /*Linux 下驱动都是应该挂在总线地下的*/

    struct module        *owner;
    const char        *mod_name;    /* used for built-in modules */

    bool suppress_bind_attrs;    /* 如果他为1 则取消暴露到文件系统中的绑定相关操作接口 */

    const struct of_device_id    *of_match_table; /* 设备树兼容属性表 */
    const struct acpi_device_id    *acpi_match_table;/* ACPI兼容属性表 */

    int (*probe) (struct device *dev); /* 设备探测接口由总线调用 */
    int (*remove) (struct device *dev);/* 设备卸载接口由总线调用 */
    void (*shutdown) (struct device *dev); /* 电源管理相关 */
    int (*suspend) (struct device *dev, pm_message_t state);
    int (*resume) (struct device *dev);
    const struct attribute_group **groups; /* 驱动属性 */

    const struct dev_pm_ops *pm;/* 设备电源管理 */

    struct driver_private *p; /* 驱动私有数据 */
};

系统给驱动开发提供了一些接口,其中driver_register和driver_unregister两个接口常使用以完成驱动的注册和卸载。

驱动注册流程

这里没有很结合源码进行分析,可以自行参考源码进行分析,3.x的内核和4.0的内核区别会有一些但是不是很大。依然有参考意义

1、driver_register
    1、不知道为什么需要检查驱动如果有probe函数总线也有就需要出一个警告,要求使用总线提供的方法,(也就是说driver里的方法要废弃??)
    2、检查目标总线上是否已经有同名驱动(因为避免设备和驱动多对多)
    3、bus_add_drv
        1、bus_get() 其实kobject.refcnt++
        2、申请分配驱动私有管理数据结构内存priv并绑定到驱动的私有数据指针上,并初始化主要是klist_devices和priv->kobj相关的。
        3、kobject_init_and_add 主要是kobject相关调用
        4、klist_add_tail 将驱动添加到bus的klist中去
        5、driver_attach(drv);/*驱动和设备的匹配 新内核新增的新异步匹配机制这里和老内核有区别 */
            1、bus_for_each_dev(bus,device_start,data,fn(struct device*,void))这个函数设备注册的时候也会调用其中的fn传入的是__driver_attach
            2、遍历bus上的klist_devices 依次__driver_attach(dev,drv)进行匹配
                1、__driver_attach
                    1、如果驱动总线的mach函数存在调用驱动总线的mach函数mach(dev,drv)返回0就算匹配上就会返回了
                    2、前一步未匹配上调用driver_probe_device(drv,dev)做了一堆检查后实际调用really_probe(dev,drv),正如函数名一样他会真正执行总线的probe函数
                        1、这里有个机制,内核会优先执行对应总线的probe函数,如果它不存在则会查看对应驱动的probe函数是否存在,存在就调用这是真正的probe操作,在这之前
                            这个函数还将sysfs下建立好了对应的文件,如果失败后面会删除并返回,同时将dev的driver句柄置空NULL,这次的驱动和设备匹配失败。
                        2、上一步成功后将进行驱动和设备的绑定driver_bound
        6、上一步如果失败就推出驱动注册,成功了继续。
        7、module_add_driver
        8、前面成功匹配以将在sysfs下建立了驱动的文件夹和文件,后的操作就是继续创建一些驱动文件接口和属性文件在驱动目录下。
        9、至此驱动注册完成,在这之中驱动的探测和绑定均以执行完毕。

驱动卸载流程

驱动的卸载
1、driver_unregister
   1、driver_remove_groups 删除对应目录下的文件
   2、bus_remove_driver
    1、删除文件
    2、klist的维护
    3、driver_detach  这个是关建,就是将之前匹配的驱动和设备解绑。
        循环
            1、 list_entry(drv->p->klist_devices.k_list.prev,。。。  找到驱动上的设备
            2、 __device_release_driver
                1、删除sysfs下的文件 因为驱动下会有文件指向设备,设备下也有文件直线驱动所以这里会删两次,一次是驱动目录下的第二次是设备下的。
                2、设备驱动句柄置空,此时设备还是在的只是没有对应驱动。

 参考:https://blog.csdn.net/qq_16777851/article/details/81459931

Linux 驱动框架---linux 驱动

标签:const   内存   devices   私有   init   意义   分配   源码   uil   

原文地址:https://www.cnblogs.com/w-smile/p/13289754.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!