为了技术,我不会停下学习的脚步,我相信我还能走二十年。
分类:
2012-09-12 13:14:07
原文地址:linux 中的 attribute 作者:cainiao413
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;
};
. 成员简单介绍
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;
私有数据。完全由驱动核心初始化并使用
2、 成员详细描述
2.1 const char *name;
总线名称,体现在sysfs文件系统的/sys/bus下,不能和别的总线名称有冲突。作为文件名称,它不能含有”/”;同时最好不含有空格,值必须有持久性。例如:
struct bus_type ycbus_type = { .name = “ycbus” };
2.2 struct bus_attribute *bus_attrs;
总线属性。表现为/sys/bus/
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);
};
其中struct attribute attr的如2.0所述。show和store方法的第一个参数都是struct bus_type指针,用来指示属性所在总线。
show方法实现数据读取。当用户空间读取属性值时,核心调用该方法实现编码,结果存放在形参buf中,注意大小不能超过过PAGE_SIZE。
store
方法实现数据保存。当用户控件设置属性值时,核心调用该方法实现解码,使用buf传递的数据解码,count指示buf传递的数据长度。注意buf信息来
自用户空间,因此在解码前应当检测数据合法性,如果数据格式或者数值和期望的不符,应该返回一个负的错误码,而不是采取不可预期或者无法恢复的动作。
另外一个需要注意的是,对于store方法,不能返回0,否则会产生死循环。因为如果store返回小于形参count,驱动核心会认为解码未完成,并以本次解码剩余的缓冲区继续调用store。我们假设一个最多一次只能解码4个字符的store函数,见如下代码调用
const char *p=”1234567890”;
attrs->store(bus,p,10);
第一次返回5,驱动核心会接着调用:
attrs->store(bus,p+4,10-4);
attrs->store(bus,p+8,10-8);
…
持续直到count为0。因此一个返回0的store会导致永久循环。
下文的设备属性和驱动属性的store有同样的限制。
2.3 struct device_attribute *dev_attrs;
默认设备属性。对于每个将要注册到该总线上的设备,在设备注册时,默认添加dev_attrs数组指定的属性。这个结构体定义如下:
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);
};
这 个结构体和struct bus_attribute的成员相类似。成员attr保存名称和权限,show和store方法分别在用户空间获取/设置属性值时调用。值得注意的是, 此处show和store的函数接口,与struct bus_attribute中的完全不同。
2.4 struct driver_attribute *drv_attrs;
默认驱动属性。对于每个将要注册到该总线上的驱动,在驱动注册时,默认添加drv_attrs数组指定的属性。这个结构体定义如下:
struct driver_attribute {
struct attribute attr;
ssize_t (*show)(struct device_driver *driver, char *buf);
ssize_t (*store)(struct device_driver *driver, const char *buf,
size_t count);
};
现 在观看这个结构体,会觉得十分熟悉。如同struct bus_attribute或struct device_attribute,attr设定属性的名称和权限,show和store方法指定用户空间数据获取/设置的编解码算法。需要注意show 和store有不同的形参列表。