类 子系统
类是一个设备的高层视图, 它抽象出了底层的实现细节,从而允许用户空间使用设备所提供的功能, 而不用关心设备是如何连接和工作的。类成员通常由上层代码所控制, 而无需驱动的明确支持。但有些情况下驱动也需要直接处理类。
几乎所有的类都显示在 /sys/class 目录中。出于历史的原因,有一个例外:块设备显示在 /sys/block目录中。在许多情况, 类子系统是向用户空间导出信息的最好方法。当类子系统创建一个类时, 它将完全拥有这个类,根本不用担心哪个模块拥有那些属性,而且信息的表示也比较友好。
为了管理类,驱动程序核心导出了一些接口,其目的之一是提供包含设备号的属性以便自动创建设备节点,所以udev的使用离不开类。 类函数和结构与设备模型的其他部分遵循相同的模式,所以真正崭新的概念是很少的。
注意:class_simple 是老接口,在2.6.13中已被删除,这里不再研究。
管理类的接口
类由 struct class 的结构体来定义:
/* * device classes */ struct class { const char * name;/*每个类需要一个唯一的名字, 它将显示在 /sys/class 中*/ struct module * owner;
struct kset subsys; struct list_head children; struct list_head devices; struct list_head interfaces; struct kset class_dirs; struct semaphore sem; /* locks both the children and interfaces lists */
struct class_attribute * class_attrs;/* 指向类属性的指针(以NULL结尾) */ struct class_device_attribute * class_dev_attrs;/* 指向类中每个设备的一组默认属性的指针 */ struct device_attribute * dev_attrs;
int (*uevent)(struct class_device *dev, char **envp, int num_envp, char *buffer, int buffer_size);/* 类热插拔产生时添加环境变量的函数 */ int (*dev_uevent)(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size);/* 类中的设备热插拔时添加环境变量的函数 */
void (*release)(struct class_device *dev);/* 把设备从类中删除的函数 */ void (*class_release)(struct class *class);/* 删除类本身的函数 */ void (*dev_release)(struct device *dev);
int (*suspend)(struct device *, pm_message_t state); int (*resume)(struct device *); };
/*类注册函数:*/ 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 *cls, const char *buf, size_t count); }; CLASS_ATTR(_name,_mode,_show,_store); int class_create_file(struct class *cls, const struct class_attribute *attr); void class_remove_file(struct class *cls, const struct class_attribute *attr);
|
在更新的内核里,这个结构体变得简洁了,删除了一些成员:
/*in Linux 2.6.26.5*/
/* * device classes */ struct class { const char *name; struct module *owner;
struct kset subsys; struct list_head devices; struct list_head interfaces; struct kset class_dirs; struct semaphore sem; /* locks children, devices, interfaces */ struct class_attribute *class_attrs; struct device_attribute *dev_attrs;
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 class_device 来表示:
struct class_device { struct list_head node;/*for internal use by the driver core only*/ struct kobject kobj;/*for internal use by the driver core only*/ struct class * class; /* 指向该设备所属的类,必须*/ dev_t devt; /* dev_t, creates the sysfs "dev" ,for internal use by the driver core only*/ struct class_device_attribute *devt_attr;/*for internal use by the driver core only*/ struct class_device_attribute uevent_attr; struct device * dev; /* 指向此设备相关的 device 结构体,可选。若不为NULL,应是一个从类入口到/sys/devices 下相应入口的符号连接,以便用户空间查找设备入口*/ void * class_data; /* 私有数据指针 */ struct class_device *parent; /* parent of this child device, if there is one */ 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);
/*类设备入口属性:*/ 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); };
CLASS_DEVICE_ATTR(_name, _mode, _show, _store);
/*创建和删除除struct class中设备默认属性外的属性*/ int class_device_create_file(struct class_device *cls, const struct class_device_attribute *attr); void class_device_remove_file(struct class_device *cls, const struct class_device_attribute *attr);
|
类接口
类子系统有一个 Linux 设备模型的其他部分找不到的附加概念,称为“接口”, 可将它理解为一种设备加入或离开类时获得信息的触发机制,结构体如下:struct class_interface { struct list_head node; struct class *class;/* 指向该接口所属的类*/
int (*add) (struct class_device *, struct class_interface *);
/*当一个类设备被加入到在 class_interface 结构中指定的类时, 将调用接口的 add 函数,进行一些设备需要的额外设置,通常是添加更多属性或其他的一些工作*/ void (*remove) (struct class_device *, struct class_interface *);/*一个接口的功能是简单明了的. 当设备从类中删除, 将调用remove 方法来进行必要的清理*/ int (*add_dev) (struct device *, struct class_interface *); void (*remove_dev) (struct device *, struct class_interface *); };
/*注册或注销接口的函数:*/ int class_interface_register(struct class_interface *class_intf); void class_interface_unregister(struct class_interface *class_intf); /*一个类可注册多个接口*/
|
阅读(902) | 评论(0) | 转发(1) |