• linux设备模型:扩展篇


    Linux设备模型组件:总线 
    一、定义:
    总线是不同IC器件之间相互通讯的通道;在计算机中,一个总线就是处理器与一个或多个不同外设之间的通讯通道;为了设备模型的目的,所有的设备都通过总线相互连接,甚至当它是一个内部的虚拟总线(如,platform总线);例如,设备模型表示在总线和它们控制的设备之间的实际连接;
    常见的总线有:PCI、ISA、EISA、VESA、USB、IIC、IIS、SPI、SCI、CAN、RS-232-C、RS-485、IEEE-488,等等;
    Linux设备模型中,一个总线由内核结构体struct bus_type描述;其结构定义如下:
    struct bus_type
    {
    const char*        name;           //总线类型的名称
    struct subsystem     subsys;         //该总线所属的子系统subsystem,代表自身---kset
    struct kset         drivers;        //该总线所使用的驱动程序的集合
    struct kset        devices;        //挂接在该总线上的所有设备的集合
    struct klist            klist_devices;  //挂接在该总线上的所有设备所组成的链表
    struct klist            klist_drivers;  //该总线所使用的驱动程序所组成的链表
    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, char** envp, int num_envp, char* buffer, int buffer_size);
    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);
    };
    每个bus_type对象都对应/sys/bus目录下的一个子目录,如,PCI总线对应于/sys/bus/pci目录;在每个这样的子目录下存在两个子目录:devices和drivers,分别对应于bus_type结构中的devices和drivers成员,其中,devices子目录描述的是连接在该总线上的所有设备,drivers子目录描述的是该总线所使用的所有驱动程序;/sys/bus目录下的所有子目录都类似;
    二、相关函数:
    1、int bus_register(struct bus_type* bus); //注册函数
    2、void bus_unregister(struct bus_type* bus); //注销函数
    3、void bus_rescan_devices(struct bus_type* bus); //扫描函数
    4、int bus_for_each_dev(struct bus_type* bus, struct device* start, void* data, int (*fn)(struct device*, void*));
       //该函数用于遍历指定总线上的已知设备;
    5、int bus_for_each_drv(struct bus_type* bus, struct device_driver* start, void* data, int (*fn)(struct device_driver*, void*));
       //该函数用于遍历指定总线上已知的驱动程序;
    6、struct device* bus_find_device(struct bus_type* bus, struct device* start, void* data, int (*match)(struct device*, void*));
       //该函数用于在指定总线上查找指定设备,并返回该设备的指针;
    三、总线属性:
    Linux设备模型中,几乎每一层都提供一个添加属性的接口,总线层也不例外;
    总线层的属性类型定义如下:
    struct bus_attribute
    {
         struct attribute attr;
         ssize_t (*show)(struct bus_type* bus, char* buf);
         ssize_t (*store)(struct bus_type* bus, const char* buf, size_t count);
    };
    int bus_create_file(struct bus_type* bus, struct bus_attribute* attr):为指定总线添加属性;
    void bus_remove_file(struct bus_type* bus, struct bus_attribute* attr):删除指定总线上的指定属性;
    备注:struct bus_type、struct bus_attribute结构均定义在/usr/src/kernels/2.6.18-8.el5-i686/include/linux/device.h文件中;

    Linux设备模型组件:设备 
    一、定义:
    Linux设备模型中,在系统的最底层,每一个设备都由一个struct device对象来描述;struct device结构用于描述设备自身的信息、与其它设备之间的关系、与总线和驱动之间的关系;其定义如下:
    struct device
    {
    struct klist        klist_children;       //设备列表中的子列表
    struct klist_node     knode_parent;     //兄弟节点
    struct klist_node     knode_driver;         //驱动程序节点
    struct klist_node     knode_bus;            //总线节点
    struct device*        parent;        //父设备节点,即,当前设备所附着到的设备
    struct kobject        kobj;                 //代表当前设备,并连接它到层次中的kobject
    char                     bus_id[BUS_ID_SIZE]; //唯一确定这个总线上的设备的字符串,即,总线上设备的位置
    struct device_attribute   uevent_attr;
    struct device_attribute*  devt_attr;
    struct semaphore     sem;      //信号量
    struct bus_type*      bus;      //总线类型,即,哪种总线
    struct device_driver*   driver;     //这个设备所使用的驱动程序
    void*           driver_data;  //一个可能被设备驱动程序所使用的私有数据
    void*           platform_data; /* Platform specific data, device core doesn't touch it */
    void*           firmware_data;  /* Firmware specific data (e.g. ACPI, BIOS data),reserved for device core*/
    struct dev_pm_info    power;
    u64*           dma_mask;      /* dma mask (if dma'able device) */
    u64            coherent_dma_mask;
    struct list_head     dma_pools;     /* dma pools (if dma'ble) */
    struct dma_coherent_mem* dma_mem;       /* internal for coherent mem override */
    struct list_head     node;        /* class_device migration path */
    struct class*       class;       /* optional */
    dev_t           devt;        /* dev_t, creates the sysfs "dev" */
    void (*release)(struct device* dev);          //释放设备的函数
    };
    二、相关函数:
    int device_register(struct device* dev):设备注册;
    void device_unregister(struct device* dev):设备注销;
    void device_initialize(struct device* dev):设备初始化;
    int device_add(struct device* dev):添加设备到设备模型的层次结构中;
    void device_del(struct device* dev):设备模型的层次结构中删除设备;
    int device_for_each_child(struct device*, void*, int (*fn)(struct device*, void*)):遍历设备的子列表;
    void device_bind_driver(struct device* dev):给设备绑定一个驱动程序;
    void device_release_driver(struct device* dev):去掉设备上的驱动程序,即,删除设备与驱动程序之间的绑定关系;
    struct device* device_create(struct class* cls, struct device* parent, dev_t devt, char* fmt, ...):创建一个设备;
    void device_destroy(struct class* cls, dev_t devt):销毁一个设备;
    struct device* get_device(struct device* dev):增加设备的引用计数;
    void put_device(struct device* dev):减少设备的引用计数;
    三、设备属性:
    struct device_attribute
    {
         struct attribute attr;
         ssize_t (*show)(struct device* dev, struct device_attribute* attr, char* buf);
         ssize_t (*store)(struct device* dev, struct device_attribute* attr, const char* buf, size_t count);
    };
    int device_create_file(struct device* dev, struct device_attribute* attr):为指定设备添加属性;
    void device_remove_file(struct device* dev, struct device_attribute* attr):删除指定设备上的指定属性;
    备注:struct device、struct device_attribute结构均定义在/usr/src/kernels/2.6.18-8.el5-i686/include/linux/device.h文件中;

    Linux设备模型组件:驱动 
    一、定义:
    系统中的每一个硬件设备都由一个驱动程序来管理;内核中使用struct device_driver结构对象来描述一个设备的驱动程序;定义如下:
    struct device_driver
    {
    const char*        name;           //设备驱动程序的名字
    struct bus_type*   bus;            //所属的总线
    struct completion  unloaded;
    struct kobject   kobj;           //内嵌的kobject对象,代表自身
    struct klist     klist_devices;  //使用该驱动程序的设备列表,即,该驱动程序所管理的所有设备
    struct klist_node  knode_bus;
    struct module*     owner;          //所属模块
    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);
    };
    二、相关函数:
    int driver_register(struct device_driver* drv):驱动程序注册;
    void driver_unregister(struct device_driver* drv):驱动程序注销;
    struct device_driver* get_driver(struct device_driver* drv):增加驱动程序引用计数;
    void put_driver(struct device_driver* drv):减少驱动程序引用计数;
    struct device_driver* driver_find(const char* name, struct bus_type* bus):在指定总线上查找指定名字的驱动程序;
    三、驱动程序属性:
    struct driver_attribute
    {
         struct attribute attr;
        ssize_t (*show)(struct device_driver* drv, char* buf);
         ssize_t (*store)(struct device_driver* drv, const char* buf, size_t count);
    };
    int driver_create_file(struct device_driver* drv, struct driver_attribute* attr); //为指定驱动程序添加属性;
    void driver_remove_file(struct device_driver* drv, struct driver_attribute* attr); //删除指定驱动程序上的指定属性;
    int driver_for_each_device(struct device_driver* drv, struct device* start, void* data, int (*fn)(struct device*, void*));
    //遍历驱动程序所管理的所有设备;
    struct device* driver_find_device(struct device_driver* drv, struct device* start, void* data, int (*match)(struct device*, void*));
    //查找驱动程序所使用的设备;
    备注:struct device_driver、struct driver_attribute结构均定义在/usr/src/kernels/2.6.18-8.el5-i686/include/linux/device.h文件中。

    Linux设备模型组件:设备类 
    一、定义:
    系统中的设备所属的类有结构体struct class对象来描述,用于表示某一类设备,它是一组具有共同属性和功能的设备的抽象体,类似于面向对象中的类的概念;所有的class对象都属于class_subsys子系统,对应于/sys/class目录;
    其结构定义如下:
    struct class
    {
    const char*               name;       //类名
    struct module*            owner;      //所属模块
    struct subsystem          subsys;     //所属子系统subsystem
    struct list_head          children;   //属于该class类型的所有子类组成的链表;
    struct list_head          devices;  //属于该class类型的所有设备class_device组成的链表;
    struct list_head              interfaces;    //类接口class_interface链表
    struct semaphore              sem;             /* locks both the children and interfaces lists */
    struct class_attribute*        class_attrs;     //类属性
    struct class_device_attribute* class_dev_attrs; //类设备属性
    int (*uevent)(struct class_device* dev, char** envp, int num_envp, char* buffer, int buffer_size);
    void (*release)(struct class_device* dev);
    void (*class_release)(struct class* class);
    };

    int class_register(struct class *cls); //类注册;
    void class_unregister(struct class *cls); //类注销;
    二、设备类属性:
    struct class_attribute
    {
         struct attribute attr;
         ssize_t (*show)(struct class* cls, char* buf);
         ssize_t (*store)(struct class*, const char* buf, size_t count);
    };
    int class_create_file(struct class* cls, const struct class_attribute* attr); //为指定设备类增加指定属性;
    void class_remove_file(struct class* cls, const struct class_attribute* attr); //删除指定设备类上的指定属性;
    备注:struct class、struct class_attribute结构均定义在/usr/src/kernels/2.6.18-8.el5-i686/include/linux/device.h文件中;

    Linux设备模型组件:类设备 
    一、定义:
    一个设备类struct class的真正目的是作为一个该类具体实例(设备)的容器使用;一个设备类的具体实例由struct class_device结构来描述;也可以这样理解:struct class类型相当于面向对象系统中的类的概念,而struct class_device类型相当于面向对象系统中的实例对象的概念;只有在应用具体实例对象的时候,它的类才有意义;
    类设备struct class_device结构定义如下:
    struct class_device
    {
    struct list_head              node;
    struct kobject               kobj;        //内嵌的kobject对象
    struct class*                  class;       //所属的设备类class
    dev_t                        devt;      //设备编号
    struct class_device_attribute* devt_attr;   //类设备属性
    struct class_device_attribute  uevent_attr; //类设备事件属性
    struct device*                 dev;        //如果存在,则创建到/sys/devices目录下相应入口的符号链接
    void*                          class_data; //类私有数据
    struct class_device*           parent;     //父设备,即,当前设备所附着到的设备
    struct attribute_group**       groups;     /* optional groups */
    void (*release)(struct class_device* dev);
    int (*uevent)(struct class_device* dev, char** envp, int num_envp, char* buffer, int buffer_size);
    char   class_id[BUS_ID_SIZE];               //类唯一标识
    };
    二、类设备相关函数
    int class_device_register(struct class_device* cd); //类设备注册;
    void class_device_unregister(struct class_device* cd); //类设备注销;
    int class_device_rename(struct class_device* cd, char* new_name); //类设备重命名;
    void class_device_initialize(struct class_device* cd); //类设备初始化;
    int class_device_add(struct class_device* cd); //把类设备对象加入到设备模型的层次结构中;
    void class_device_del(struct class_device* cd); //把类设备对象从设备模型的层次结构中删除;
    struct class_device * class_device_get(struct class_device* cd); //给类设备对象增加引用计数;
    void class_device_put(struct class_device* cd); //给类设备对象减少引用计数;
    备注:每一个设备类class对象都包含一个类设备class_device对象的链表,而每一个类设备class_device对象又表示一个逻辑设备,并通过类设备struct class_device结构中的dev成员(一个指向struce device的指针)关联到一个物理设备上;这样,一个逻辑设备总是对应于一个物理设备;但是,一个物理设备却可能对应多个逻辑设备。
    三、类设备属性:
    struct class_device_attribute
    {
         struct attribute attr;
         ssize_t (*show)(struct class_device* cls, char* buf);
         ssize_t (*store)(struct class_device* cls, const char* buf, size_t count);
    };
    int class_device_create_file(struct class_device* cd, const struct class_device_attribute* attr); //为指定类设备增加指定属性;
    void class_device_remove_file(struct class_device* cd, const struct class_device_attribute* attr); //删除指定类设备上的指定属性;
    int class_device_create_bin_file(struct class_device* cd, struct bin_attribute* attr);
    void class_device_remove_bin_file(struct class_device* cd, struct bin_attribute* attr);
    四、类接口:
    当设备加入或离开类时,将引发class_interface中的成员函数被调用;
    struct class_interface
    {
         struct list_head node;
         struct class*     class; //对应的设备类class
         int (*add)(struct class_device* cd, struct class_interface* ci);     //设备加入时触发
         void (*remove)(struct class_device* cd, struct class_interface* ci); //设备移除时触发
    };
    int class_interface_register(struct class_interface* ci); //类接口注册;
    void class_interface_unregister(struct class_interface* ci); //类接口注销;
    struct class* class_create(struct module* owner, char* name); //创建类;
    void class_destroy(struct class* cls); //销毁类;
    struct class_device *class_device_create(struct class *cls, struct class_device *parent, dev_t devt, struct device *device, char *fmt, ...); //创建类设备
    void class_device_destroy(struct class *cls, dev_t devt);//销毁类设备
    备注:struct class_device、struct class_device_attribute、struct class_interface结构均定义在/usr/src/kernels/2.6.18-8.el5-i686/include/linux/device.h文件中。

    示例代码下载链接:http://download.csdn.net/detail/klcf0220/5865769

    Input子系统分析 下载链接:http://download.csdn.net/detail/klcf0220/5874587

  • 相关阅读:
    linux下的socket编程(3)--server端的简单示例
    高级I/O函数
    补充:memset透彻分析
    空间复杂度为0的数据交换
    排序算法一:直接插入排序
    [Github]watch和star的区别
    计算机网络总结(四)
    计算机网络总结(三)
    Java集合
    计算机网络总结(二)
  • 原文地址:https://www.cnblogs.com/klcf0220/p/3235697.html
Copyright © 2020-2023  润新知