现在的位置: 首页 > 综合 > 正文

Linux设备模型

2013年08月01日 ⁄ 综合 ⁄ 共 6133字 ⁄ 字号 评论关闭

Overview

Linuxsysfs文件系统一般mount/sys目录。本文主要介绍sysfs文件系统中设备驱动模型的建立过程,内核版本2.6.29

设备驱动信息主要用来表示设备以及驱动的层次关系,以及处理热插拔等。/sys中与之相关的数据有:

class              代表一类设备,比如mtdnettty等等

bus         总线,比如PCIUSBI2C

device     代表一个设备

driver      代表一个驱动

 

以下是一些sysfs中的全局变量:

//  /sys/class

struct kset * class_kset = kset_create_and_add("class", NULL, NULL);                 

//     /sys/bus

struct kset * bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);    

//     /sys/devices

struct kset * devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL);   

 

1.     Class

1.1           class的基本结构

struct class {

         const char            *name;

         struct module               *owner;

         struct class_attribute             *class_attrs;

         struct device_attribute           *dev_attrs;

         struct kobject                         *dev_kobj;

         int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env);

         void (*class_release)(struct class *class);

         void (*dev_release)(struct device *dev);

         int (*suspend)(struct device *dev, pm_message_t state);

         int (*resume)(struct device *dev);

         struct pm_ops *pm;

         struct class_private *p;

};

struct class_private {

         struct kset class_subsys;

         struct list_head class_devices;

         struct list_head class_interfaces;

         struct kset class_dirs;

         struct mutex class_mutex;

         struct class *class;

};

classsysfs中的层次由struct class_private决定。struct class只是class_private的封装。

struct class_private::class_subsys.kobj.kset = class_kset;  // 父目录为/sys/class

struct class_private::class_subsys.kobj->name代表这个class/sys/class中显示的名字

struct class::dev_attrs为设备属性,往class中添加设备的时候,这些属性会自动添加到设备目录下。

1.2           新建class

新建class有两种方法:静态创建和动态创建。

l         静态创建

static struct class i2c_adapter_class = {

       .owner                  = THIS_MODULE,

       .name                    = "i2c-adapter",

       .dev_attrs              = i2c_adapter_attrs,

       .class_attrs   = ...

};

int retval = class_register(&i2c_adapter_class)

 

l         动态创建

i2c_dev_class = class_create(THIS_MODULE, "i2c-dev");

class_create分配申请一块空间给class然后对nameownerclass_release函数赋值并最终调用class_register

class_register

根据struct class的值,设置struct class_private

调用add_class_attrsclass中添加属性。

l         class attrs

class的属性最终是在/sys/class/<new class>/目录下以文件的形式存在。用户程序可以直接对这些属性进行读写。如果要静态创建属性,可以在定义class时对.class_attrs域赋值使其指向要添加的attr数组。如果要动态创建。可以通过函数class_create_file添加。

int class_create_file(struct class *cls, const struct class_attribute *attr);

 

如果是动态创建的属性,需要在模块卸载时调用class_remove_file释放。

如果是静态创建的属性,在调用class_unregister时会自动释放。

2.     Bus

2.1 bus的基本结构

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 (*suspend_late)(struct device *dev, pm_message_t state);

         int (*resume_early)(struct device *dev);

         int (*resume)(struct device *dev);

         struct pm_ext_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;

};

class类似,bussysfs中的显示由struct bus_type_private决定,struct bus_type只是一个封装。

struct bus_type_private::subsys.kobj代表/sys/bus/<bus>目录。

struct bus_type_private::subsys.kobj.kset = bus_kset; // 默认父目录为/sys/bus/

struct bus_type_private::subsys.kobj.ktype = &bus_ktype;  // bus的属性操作

struct bus_type_private::subsys.kobj.name = <bus/sys/bus/目录下显示的名字>;

/sys/bus/目录,每创建成功一个<bus>,都会自动创建两个子目录driversdevices,分别代表连到此<bus>的设备和驱动。在driversdevices子目录下,每新建一个driver,会把struct bus_type中的drv_attrs属性赋给那个driver;每创建一个device,会把struct bus_typedev_attrs赋给那个device

2.2 新建bus

struct bus_type i2c_bus_type = {

       .name             = "i2c",

       .dev_attrs              = i2c_dev_attrs,

       .match           = i2c_device_match,

       .uevent           = i2c_device_uevent,

       .probe            = i2c_device_probe,

       .remove          = i2c_device_remove,

       .shutdown      = i2c_device_shutdown,

       .suspend         = i2c_device_suspend,

       .resume          = i2c_device_resume,

       .bus_attr         = …

};

int ret = bus_register(&i2c_bus_type);

 

int bus_register(struct bus_type *bus);

分配内存给struct bus_type_private;

根据struct bus_type的域设置bus_type_private;

根据.bus_attr设置bus的属性,这些属性在bus_unregister时会被自动释放。(bus属性也可通过bus_create_file动态添加,但所有动态添加的属性都要在卸载时通过bus_remove_file释放。)

 

3Device

3.1 Device的基本结构

struct device {

         struct klist           klist_children;

         struct klist_node knode_parent;     /* node in sibling list */

         struct klist_node knode_driver;

         struct klist_node knode_bus;

         struct device                 *parent;

         struct kobject kobj;

         char   bus_id[BUS_ID_SIZE];        /* position on parent bus */

         const char            *init_name; /* initial name of the device */

         struct device_type       *type;

         unsigned              uevent_suppress:1;

         struct semaphore          sem;  /* semaphore 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            *driver_data;       /* data private to the driver */

         void            *platform_data;  /* Platform specific data, device core doesn't touch it */

         struct dev_pm_info      power;

         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;

         spinlock_t           devres_lock;

        

抱歉!评论已关闭.