2014-09-26 2 views
1

Я работаю с драйвером ядра для устройства 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, чтобы взять параметр? Или есть лучшая система, которую я должен использовать для этого? Я посмотрел на debugfs, и мне кажется, что мне нужно поддерживать значения в памяти для него.

ответ

1

Вы можете попробовать контейнер container_of(). Просто заполните данные атрибутов в более крупной структуре.

Вот пример создания 100 атрибутов в большой структуре big_kattr. Параметр 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 
Смежные вопросы