zoukankan      html  css  js  c++  java
  • Linux设备管理(四):总线、设备、驱动三者之间的联系

    /************************************************************************************

    *本文为个人学习记录,如有错误,欢迎指正。

    *本文参考资料: 

    *        https://www.cnblogs.com/andtt/articles/2178905.html

    *        https://blog.csdn.net/yueqian_scut/article/details/46694417

    *        https://blog.csdn.net/babyzhaoshu521/article/details/60350843

    ************************************************************************************/

    1. 总线

    在物理层面上,总线代表着同类设备需要共同遵守的工作时序,不同的总线对于物理电平的要求是不一样的,对于每个比特的电平维持宽度也是不一样,而总线上传递的命令也会有自己的格式约束。如I2C总线、USB总线、PCI总线等等。以I2C总线为例,在同一组I2C总线上连接着不同的I2C设备。

    在软件层面上,总线的主要作用是管理设备与驱动。

    Linux内核中使用struct bus_type描述一个总线,其中包含了该总线的所有信息。

    //所在文件/kernel/drivers/base/base.h
    struct bus_type {
        const char        *name;                 //总线类型名称
        struct bus_attribute    *bus_attrs;      //总线属性
        struct device_attribute    *dev_attrs;   //设备属性
        struct driver_attribute    *drv_attrs;   //驱动程序属性
    
        int (*match)(struct device *dev, struct device_driver *drv);
        int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
        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 dev_pm_ops *pm;
    
        struct bus_type_private *p;
    };
    
    struct bus_type_private {
        struct kset subsys;
        struct kset *drivers_kset;
        struct kset *devices_kset;
        struct klist klist_devices;
        struct klist klist_drivers;
        struct blocking_notifier_head bus_notifier;
        unsigned int drivers_autoprobe:1;
        struct bus_type *bus;
    };
    struct bus_type

    2. 设备

    设备代表真实的、具体的物理器件。在软件层面上,用器件的独特的参数属性来代表该器件。如I2C总线上连接的I2C从设备都有一个标识自己的设备地址,由这个设备地址来确定主设备发过来的命令是否该由它来响应。

    struct device是一个基类,被设备相关的数据结构包含,其中包含了该设备的信息。

    struct device {
        struct device          *parent;
        struct device_private  *p;
        struct kobject kobj;
        const char          *init_name;  /* initial name of the device */
        struct device_type  *type;
        struct mutex        mutex;       /* mutex to synchronize calls to its driver.*/
    
        struct bus_type    *bus;         /* type of bus device is on */
        struct device_driver *driver;    /* which driver has allocated this device */
        void   *platform_data;           /* Platform specific data, device core doesn't touch it */
        struct dev_pm_info    power;
    
    #ifdef CONFIG_NUMA
        int        numa_node;    /* NUMA node this device is close to */
    #endif
        u64        *dma_mask;    /* dma mask (if dma'able device) */
        u64        coherent_dma_mask;
        struct device_dma_parameters *dma_parms;
        struct list_head    dma_pools;    /* dma pools (if dma'ble) */
        struct dma_coherent_mem    *dma_mem; /* internal for coherent mem override */
        struct dev_archdata    archdata;
    #ifdef CONFIG_OF
        struct device_node    *of_node;
    #endif
    
        dev_t    devt;    /* dev_t, creates the sysfs "dev" */
        spinlock_t        devres_lock;
        struct list_head    devres_head;
        struct klist_node    knode_class;
        struct class        *class;
        const struct attribute_group **groups;    /* optional groups */
        void    (*release)(struct device *dev);
    };
    
    
    struct device_private {
        struct klist klist_children;
        struct klist_node knode_parent;
        struct klist_node knode_driver;
        struct klist_node knode_bus;
        void *driver_data;
        struct device *device;
    };
    struct device

    3. 驱动

    驱动代表着操作设备的方式和流程。驱动主要包括两部分,第一是通过对SoC的控制寄存器进行编程,按总线要求输出时序和命令,成功地与外围设备进行交互;第二是对第一步中得到的数据进行处理,并向应用层提供特定格式的数据。

    struct driver是一个基类,被驱动相关的数据结构包含,其中包含了该驱动的信息。

    struct device_driver {
        const char        *name;
        struct bus_type   *bus;
        struct module     *owner;
        const char        *mod_name;    /* used for built-in modules */
        bool suppress_bind_attrs;       /* disables bind/unbind via sysfs */
    #if defined(CONFIG_OF)
        const struct of_device_id    *of_match_table;
    #endif
        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;
    };
    
    
    struct driver_private {
        struct kobject kobj;
        struct klist klist_devices;
        struct klist_node knode_bus;
        struct module_kobject *mkobj;
        struct device_driver *driver;
    };
    struct device_driver

    4. 总线、设备、驱动三者之间的联系

    上图为平台总线设备驱动模型的整体框架。

    上图为平台总线设备驱动模型的整体框架。

    在总线设备驱动模型中,需关心总线、设备和驱动这3个实体,总线将设备和驱动绑定。

    当系统向内核注册每一个驱动程序时,都要通过调用驱动注册函数(xxx_driver_register)将驱动程序注册到总线,并将其放入所属总线的drv链表中,注册驱动的时候会调用所属总线的match函数寻找该总线上与之匹配的每一个设备,如果找到与之匹配的设备则会调用相应的probe函数将相应的设备和驱动进行绑定;同样的当系统向内核注册每一个设备时,都要通过调用设备注册函数(xxx_device_register)将设备注册到总线,并将其放入所属总线的dev链表中,注册设备的时候同样也会调用所属总线的match函数寻找该总线上与之匹配的每一个驱动程序,如果找到与之匹配的驱动程序时会调用相应的probe函数将相应的设备和驱动进行绑定;而这一匹配的过程是由总线自动完成的。

    总线在匹配设备和驱动之后驱动要考虑一个这样的问题,设备对应的软件数据结构代表着静态的信息,真实的物理设备此时是否正常还不一定,因此驱动需要探测这个设备是否正常。总线的管理代码中会有这样的逻辑:

     if(match(device, driver) == OK)
    
      driver->probe();

    总线匹配设备和驱动之后,驱动探测到设备正常,开始创建设备文件。调用class_create()、device_create()函数在/dev目录下创建相应的设备文件,其内部原理是通过sysfs文件系统、uevent事件通知机制和后台应用服务mdev程序配合能够成功地在/dev目录创建对应的设备文件。详见Linux设备文件的创建

  • 相关阅读:
    Java NIO系列教程(六) 多路复用器Selector
    Java NIO系列教程(五)Buffer
    Java NIO系列教程(四) Scatter/Gather
    ORA-00600: internal error code, arguments: [kcratr_nab_less_than_odr], [1], [1498], [18713], [18720]
    统计单词出现的最多次数(Trie树)
    毁灭梦想的5个方法
    windows内核Api的学习
    android创建目录和文件和安装其它apk
    Java 遍历指定文件夹及子文件夹下的文件
    sqlplus的非交互式使用
  • 原文地址:https://www.cnblogs.com/linfeng-learning/p/9324268.html
Copyright © 2011-2022 走看看