我正在使用I2C设备的内核驱动程序,到目前为止,我一直在使用sysfs DEVICE_ATTR助手创建简单的属性。现在我需要制作一长串可用的属性,如/sys/bus/i2c/device/.../param0,../ param1等,但为每个属性编写一个函数似乎效率低下甚至是错误使用sysfs系统。例如:
static DEVICE_ATTR(param0, S_IRUGO, NULL, foo_set_param0);
static DEVICE_ATTR(param1, S_IRUGO, NULL, foo_set_param1);
...
static DEVICE_ATTR(param50, S_IRUGO, NULL, foo_set_param50);
设备上的值经常变化并且读取它们很昂贵,因此不断阅读它们或使用一个功能来读取它们并不是真正的选择。我有一点C新手,所以也许有一些非常明显我缺失的东西,但是你可以在sysfs show callback上使用包装器来获取参数吗?或者,我应该使用更好的系统吗?我查看了debugfs,似乎我需要为它维护内存中的值。
答案 0 :(得分:2)
您可以尝试使用container_of()宏。只需在更大的结构中填充属性数据即可。
以下是在big_kattr大结构中创建100个属性的示例。参数是UNIT_NUM。
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#define UNIT_NUM 100
typedef struct {
struct kobj_attribute k_obj;
int num;
} big_kattr;
static struct kobject *register_kobj;
// rw functions
static ssize_t __used store_value(struct kobject *kp, struct kobj_attribute *attr, const char *buf, size_t count){
big_kattr *a = container_of(attr, big_kattr, k_obj);
sscanf(buf, "%du", &a->num);
return count;
}
static ssize_t show_value(struct kobject *kp, struct kobj_attribute *attr, char *buf) {
big_kattr *a = container_of(attr, big_kattr, k_obj);
return sprintf(buf, "%d\n", a->num);
}
// put attribute to attribute group
static struct attribute * unit_attrs[UNIT_NUM + 1];
static big_kattr full_unit_attrs[UNIT_NUM];
static struct attribute_group unit_attr_group;
static int hello_init(void){
int i;
memset(full_unit_attrs, 0, sizeof(full_unit_attrs));
memset(unit_attrs, 0, sizeof(unit_attrs));
memset(&unit_attr_group, 0, sizeof(unit_attr_group));
for(i=0; i<UNIT_NUM; i++){
char * str = kmalloc(32, GFP_KERNEL);
sprintf(str, "unit-%03d",i);
full_unit_attrs[i].k_obj.attr.name = str;
full_unit_attrs[i].k_obj.attr.mode = S_IWUSR | S_IRUGO;
full_unit_attrs[i].k_obj.show = show_value;
full_unit_attrs[i].k_obj.store = store_value;
full_unit_attrs[i].num = i;
unit_attrs[i] = &(full_unit_attrs[i].k_obj.attr);
}
unit_attr_group.attrs = unit_attrs;
// create sysfs object ( /sys/kernel/many directory )
register_kobj = kobject_create_and_add("many", kernel_kobj);
if (!register_kobj)
return -ENOMEM;
//create all attributes (files)
if(sysfs_create_group(register_kobj, &unit_attr_group)){
kobject_put(register_kobj);
return -ENOMEM;
}
return 0;
}
static void hello_exit(void){
int i;
kobject_put(register_kobj);
for(i=0; i<UNIT_NUM; i++)
kfree(full_unit_attrs[i].k_obj.attr.name);
}
MODULE_LICENSE("Dual BSD/GPL");
module_init(hello_init);
module_exit(hello_exit);
示例:
cat /sys/kernel/many/unit-077
echo 12345 > /sys/kernel/many/unit-088
cat /sys/kernel/many/unit-088