关于sysfs的属性文件
预备知识
在linux/include/linux/sysfs.h中:
/* FIXME * The *owner field is no longer used, but leave around * until the tree gets cleaned up fully. */ struct attribute { const char * name; struct module * owner; mode_t mode; }; struct attribute_group { const char * name; struct attribute ** attrs; }; /** * Use these macros to make defining attributes easier. See include/linux/device.h * for examples.. */ __ATTR是以后的几个属性文件定义的基本属性 #define __ATTR(_name,_mode,_show,_store) { \ .attr = {.name = __stringify(_name), .mode = _mode }, \ .show = _show, \相对于读操作时调用的函数 .store = _store, \ } #define __ATTR_RO(_name) { \ .attr = { .name = __stringify(_name), .mode = 0444 }, \ .show = _name##_show, \只有只读的文件操作函数 } #define __ATTR_NULL { .attr = { .name = NULL } } struct sysfs_ops { ssize_t (*show)(struct kobject *, struct attribute *,char *); ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t); }; |
BUS_ATTR DRIVER_ATTR CLASS_ATTR CLASS_DEVICE_ATTR DEVICE_ATTR
DEVICE_ATTR是关于设备的属性文件宏定义 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); }; #define DEVICE_ATTR(_name,_mode,_show,_store) \ struct device_attribute dev_attr_##_name = __ATTR(_name,_mode,_show,_store) extern int __must_check device_create_file(struct device *device,struct device_attribute * entry); extern void device_remove_file(struct device * dev, struct device_attribute * attr); int device_create_file(struct device * dev, struct device_attribute * attr) { int error = 0; if (get_device(dev)) { error = sysfs_create_file(&dev->kobj, &attr->attr); put_device(dev); } return error; } void device_remove_file(struct device * dev, struct device_attribute * attr) { if (get_device(dev)) { sysfs_remove_file(&dev->kobj, &attr->attr); put_device(dev); } } |
BUS_ATTR 是关于总线的属性文件宏定义 linux/include/linux/device.h struct bus_attribute { struct attribute attr; ssize_t (*show)(struct bus_type *, char * buf); ssize_t (*store)(struct bus_type *, const char * buf, size_t count); }; #define BUS_ATTR(_name,_mode,_show,_store) \ struct bus_attribute bus_attr_##_name = __ATTR(_name,_mode,_show,_store) extern int __must_check bus_create_file(struct bus_type *, struct bus_attribute *); extern void bus_remove_file(struct bus_type *, struct bus_attribute *); linux/drivers/base/bus.c static struct sysfs_ops bus_sysfs_ops = { .show = bus_attr_show, .store = bus_attr_store, }; int bus_create_file(struct bus_type * bus, struct bus_attribute * attr) { int error; if (get_bus(bus)) { error = sysfs_create_file(&bus->subsys.kobj, &attr->attr); put_bus(bus); } else error = -EINVAL; return error; } void bus_remove_file(struct bus_type * bus, struct bus_attribute * attr) { if (get_bus(bus)) { sysfs_remove_file(&bus->subsys.kobj, &attr->attr); put_bus(bus); } } static struct kobj_type bus_ktype = { .sysfs_ops = &bus_sysfs_ops, }; static int bus_uevent_filter(struct kset *kset, struct kobject *kobj) { struct kobj_type *ktype = get_ktype(kobj); if (ktype == &bus_ktype) return 1; return 0; } static struct kset_uevent_ops bus_uevent_ops = { .filter = bus_uevent_filter, }; static decl_subsys(bus, &bus_ktype, &bus_uevent_ops); |
CLASS_ATTR是关于设备的属性文件宏定义 linux/include/linux/device.h struct class_attribute { struct attribute attr; ssize_t (*show)(struct class *, char * buf); ssize_t (*store)(struct class *, const char * buf, size_t count); }; #define CLASS_ATTR(_name,_mode,_show,_store) \ struct class_attribute class_attr_##_name = __ATTR(_name,_mode,_show,_store) extern int __must_check class_create_file(struct class *, const struct class_attribute *); extern void class_remove_file(struct class *, const struct class_attribute *); linux/drivers/base/class.c int class_create_file(struct class * cls, const struct class_attribute * attr) { int error; if (cls) { error = sysfs_create_file(&cls->subsys.kobj, &attr->attr); } else error = -EINVAL; return error; } void class_remove_file(struct class * cls, const struct class_attribute * attr) { if (cls) sysfs_remove_file(&cls->subsys.kobj, &attr->attr); } |
CLASS_DEVICE_ATTR是关于类设备的属性文件宏定义 类也是一个设备 linux/include/linux/device.h struct class_device_attribute { struct attribute attr; ssize_t (*show)(struct class_device *, char * buf); ssize_t (*store)(struct class_device *, const char * buf, size_t count); }; #define CLASS_DEVICE_ATTR(_name,_mode,_show,_store) \ struct class_device_attribute class_device_attr_##_name = \ __ATTR(_name,_mode,_show,_store) extern int __must_check class_device_create_file(struct class_device *, const struct class_device_attribute *); linux/drivers/base/class.c int class_device_create_file(struct class_device * class_dev, const struct class_device_attribute * attr) { int error = -EINVAL; if (class_dev) error = sysfs_create_file(&class_dev->kobj, &attr->attr); return error; } |
DRIVER_ATTR 是关于驱动的属性文件宏定义 linux/include/linux/device.h struct driver_attribute { struct attribute attr; ssize_t (*show)(struct device_driver *, char * buf); ssize_t (*store)(struct device_driver *, const char * buf, size_t count); }; #define DRIVER_ATTR(_name,_mode,_show,_store) \ struct driver_attribute driver_attr_##_name = __ATTR(_name,_mode,_show,_store) extern int __must_check driver_create_file(struct device_driver *, struct driver_attribute *); extern void driver_remove_file(struct device_driver *, struct driver_attribute *); extern int __must_check 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 *)); linux/drivers/base/driver.c /** * driver_create_file - create sysfs file for driver. * @drv: driver. * @attr: driver attribute descriptor. */ int driver_create_file(struct device_driver * drv, struct driver_attribute * attr) { int error; if (get_driver(drv)) { error = sysfs_create_file(&drv->kobj, &attr->attr); put_driver(drv); } else error = -EINVAL; return error; } /** * driver_remove_file - remove sysfs file for driver. * @drv: driver. * @attr: driver attribute descriptor. */ void driver_remove_file(struct device_driver * drv, struct driver_attribute * attr) { if (get_driver(drv)) { sysfs_remove_file(&drv->kobj, &attr->attr); put_driver(drv); } } |