linux驱动模型——platform(1)

一.驱动模型包含什么?

    1.1. 类class

        1.1.2. 它能够自动创建/dev下的设备节点,不需要mknod /dev/xxx c x x创建。当然class还有其另外的作用,且自动创建设备节点的还有udev系统,udev是处于用户空间的,其自动创建设备节点也是依赖于sysfs文件系统中提供的class类

    1.2. 总线bus

        1.2.1. 总线是处理器和设备之间的通道。总线有多种类型,每种总线可以挂载多个设备

    1.3. 设备device

        1.3.1. 驱动程序是在CPU运行时,提供操作的软件接口。所有的设备必须有与之配套驱动程序才能正常工作。一个驱动程序可以驱动多个类似或者完全不同的设备。

    1.4. 驱动driver

        1.4.1. 设备就是连接在总线上的物理实体。设备是有功能之分的。具有相同功能的设备被归到一个类,如输入设备(鼠标,键盘,游戏杆等)。

    1.5. 三者的关系

        1.5.1. 总线上有两个重要的链表:1)设备(device)链表;2)驱动(driver)链表

        1.5.2. 每次出现一个设备就要向总线汇报,每次出现一个驱动,也要向总线注册。系统初始化的时候,会扫描连接了哪些设备,为每一个设备建立起一个struct device的变量,并加入设备链表;每次注册一个驱动,就要准备一个struct device_driver结构的变量,并加入驱动链表。这样所有的设备都挂载到总线上,当加载驱动时,驱动就去总线上找到自己对应的设备,或者先把驱动注册上,来了一个设备就去总线找驱动。如果只有设备却没有对应的驱动,那么设备无法工作,如果只有驱动却没有设备,驱动也起不了任何作用。

        1.5.3. 每种总线下面可以挂载许多设备。(通过kset devices)

        1.5.4. 每种总线下可以用很多驱动。(通过包含一个kset drivers)

        1.5.5. 每个驱动可以处理一个或多个设备。

    1.6. 其它内容

        1.6.1. 对象的引用计数

            1.6.1.1. 通常一个内核对象被创建时,不可能知道该对象存活的时间。跟踪此对象生命周期的一个方法是使用引用计数。当内核中没有代码持有该对象的引用时,该对象将结束自己的有效生命周期,并且可以被删除

        1.6.2. sysfs表述sysfs表述

            1.6.2.1. 在sysfs中显示的每一个对象,都对应一个kobject,它被用来与内核交互并创建它的可见表述。

            1.6.2.2. 数据结构关联:从整体上看,设备模型是一个友好而复杂的数据结构,通过在其间的大量连接而构成一个多层次的体系结构。Kobject实现了该结构并把它们聚合在一起

        1.6.3. uevent事件处理

            1.6.3.1. 当系统中的硬件被热插拔时,在kobject子系统控制下,将产生事件以通知用户空间

            1.6.3.2. Kobjects 在内核中对应有一套申请,初始化,添加,注册,计数操作,释放等函数

二. 为什么需要设备驱动模型

    2.1. linux 2.6版本中正式引入设备驱动模型,目的是在设备越来越多,功耗要求等新特性要求的情况下让驱动体系更易用、更优秀。

    2.2. 设备驱动模型负责统一实现和维护一些特性,诸如:电源管理、热插拔、对象生命周期、用户空间和驱动空间的交互等基础设施

    2.3. 设备驱动模型目的是简化驱动程序编写,但是客观上设备驱动模型本身设计和实现很复杂

三. 驱动模型中重要结构体

    3.1. kobject结构体

        3.1.1. 定义在linux/kobject.h中

struct kobject {
    const char        *name;            ///*kobject的名字,每个kobject都对应着sysfs下的一个文件夹,该名字也是对应的文件夹的名字。*/
    struct list_head    entry;            ///*双向链表指针,用于将同一kset集合中的kobject链接到一起,便于访问*/
    struct kobject        *parent;            ///*kobject对应的父kobject节点,在sysfs表现为上一级目录*/
    struct kset        *kset;            ///*kobject所在的集合的指针,kset概念将在kset一节中描述*/
    struct kobj_type    *ktype;            // /*kobject对象类型指针,随后将会介绍*/
    struct sysfs_dirent    *sd;                // /*sd用于表示VFS文件系统的目录项,由此可见它是设备与文件之间的桥梁。在sysfs节会对此结构进行分析*/
    struct kref        kref;                // /*对象引用计数器。
    unsigned int state_initialized:1;
    unsigned int state_in_sysfs:1;
    unsigned int state_add_uevent_sent:1;
    unsigned int state_remove_uevent_sent:1;
    unsigned int uevent_suppress:1;
};
View Code

    3.2. kobj_type结构体

        3.2.1. 很多书中简称为ktype,每一个kobject都需要绑定一个ktype来提供相应功能

        3.2.2. 关键点1:sysfs_ops,提供该对象在sysfs中的操作方法(show和store)

        3.2.3. 关键点2:attribute,提供在sysfs中以文件形式存在的属性,其实就是应用接口

struct kobj_type {
    void (*release)(struct kobject *kobj);
    const struct sysfs_ops *sysfs_ops;
    struct attribute **default_attrs;
    const struct kobj_ns_type_operations *(*child_ns_type)(struct kobject *kobj);
    const void *(*namespace)(struct kobject *kobj);
};
View Code

    3.3. kset结构体

        3.3.1. kset与kobject关系

 

/**
 * struct kset - a set of kobjects of a specific type, belonging to a specific subsystem.
 *
 * A kset defines a group of kobjects.  They can be individually
 * different "types" but overall these kobjects all want to be grouped
 * together and operated on in the same manner.  ksets are used to
 * define the attribute callbacks and other common events that happen to
 * a kobject.
 *
 * @list: the list of all kobjects for this kset
 * @list_lock: a lock for iterating over the kobjects
 * @kobj: the embedded kobject for this kset (recursion, isn't it fun...)
 * @uevent_ops: the set of uevent operations for this kset.  These are
 * called whenever a kobject has something happen to it so that the kset
 * can add new environment variables, or filter out the uevents if so
 * desired.
 */
struct kset {
    struct list_head list;
    spinlock_t list_lock;
    struct kobject kobj;
    const struct kset_uevent_ops *uevent_ops;
};
View Code

    3.4. bus_type结构体

        3.4.1. match函数

            3.4.1.1.  match方法用来对总线下的device和driver进行匹配。理论上每种总线的匹配算法是不同的,但是实际上一般都是看name的

        3.4.2. uevent函数

            3.4.2.1. 产生事件以通知用户空间

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;
};
View Code

    3.5. device结构体

        3.5.1. struct device是硬件设备在内核驱动框架中的抽象,是所有设备共有部分的集合      

        3.5.2. device_register用于向内核驱动框架注册一个设备

        3.5.3. 通常device不会单独使用,而是被包含在一个具体设备结构体中,如struct usb_device有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;/* Like dma_mask, but for
                         alloc_coherent mappings as
                         not all hardware supports
                         64 bit addresses for consistent
                         allocations such descriptors. */

    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 */
    /* arch specific additions */
    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);
};
View Code

      3.6. device_driver结构体

            3.6.1. struct device_driver是驱动程序在内核驱动框架中的抽象

            3.6.2. 关键元素1:name,驱动程序的名字,很重要,经常被用来作为驱动和设备的匹配依据

            3.6.3. 关键元素2:probe,驱动程序的探测函数,用来检测一个设备是否可以被该驱动所管理

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;
};
View Code

 

参考《朱老师.linux设备驱动模型》

索引文献:https://blog.csdn.net/lindonghai/article/details/8111744

索引文献:https://blog.csdn.net/zhoujiaxq/article/details/7646050

posted @ 2019-01-03 14:32  三七鸽  阅读(324)  评论(0编辑  收藏  举报