proc目录详解:https://blog.csdn.net/qq_39974998/article/details/130536491
一、DEVICE_ATTR
在调试驱动的时候我们一般会对于驱动中某一个属性或者变量进行操作,或者是控制gpio口,这个时候我们可以在驱动中创建对应的属性,从而在应用程序或者控制台对驱动的属性进行设置,sysfs可以通过sysfs_create_files和sysfs_create_group()来创建,其中使用DEVICE_ATTR来创建属性文件
这个宏定义在kernel/include/linux/device.h中,函数定义为:
1 2 3 4 5 6 7 8 9
| #define DEVICE_ATTR(_name, _mode, _show, _store) \ struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
#define __ATTR(_name, _mode, _show, _store) { \ .attr = {.name = __stringify(_name), \ .mode = VERIFY_OCTAL_PERMISSIONS(_mode) }, \ .show = _show, \ .store = _store, \ }
|
mode为文件的权限,定义在kernel/include/uapi/linux/stat.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| #define S_IRWXU 00700 #define S_IRUSR 00400 #define S_IWUSR 00200 #define S_IXUSR 00100 #define S_IRWXG 00070 #define S_IRGRP 00040 #define S_IWGRP 00020 #define S_IXGRP 00010 #define S_IRWXO 00007 #define S_IROTH 00004 #define S_IWOTH 00002 #define S_IXOTH 00001
|
二、device_attribute
1 2 3 4 5 6 7 8
| 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); };
|
三、创建sysfs文件
法1:sysfs_create_files
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| static ssize_t led_store(struct device *dev,struct device_attribute *attr, const char *buf, size_t len) { printk("led_store()\n"); return len; }
static ssize_t led_show(struct device *dev, struct device_attribute*attr, char *buf) { printk("led_show()\n"); returnpr_info("store\n"); }
static DEVICE_ATTR(led_sysfs, S_IWUSR, led_show,led_store);
static const struct attribute *atk_imx6ul_led_sysfs_attrs[] = { &dev_attr_led_sysfs.attr, NULL, };
sysfs_create_files(&led_device.device->kobj,atk_imx6ul_led_sysfs_attrs); sysfs_remove_file(&led_device.device->kobj, atk_imx6ul_led_sysfs_attrs);
|
其中kobj的定义为
1 2 3 4
| kobject在设备结构体中的描述: struct platform_device —>struct device dev —>struct kobject kobj
|
法2(推荐):sysfs_create_group()
使用:将上面的attribute结构体再进行封装
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| static ssize_t led_store(struct device *dev,struct device_attribute *attr, const char *buf, size_t len) { printk("led_store()\n"); return len; }
static ssize_t led_show(struct device *dev, struct device_attribute*attr, char *buf) { printk("led_show()\n"); returnpr_info("store\n"); }
static DEVICE_ATTR(led_sysfs, S_IWUSR, led_show,led_store);
static struct attribute *atk_imx6ul_led_sysfs_attrs[] = { &dev_attr_led_sysfs.attr, NULL, };
static const struct attribute_group dev_attr_grp = { .attrs = atk_imx6ul_led_sysfs_attrs, }; sysfs_create_group(&led_device.device.kobj, &dev_attr_grp) sysfs_remove_group(&client->dev.kobj, &dev_attr_group);
|
四、验证
直接在终端下通过find命令查找结点,这里只是一个示例,并不是上面举的例子

实验echo命令调用store函数

这里cat没有写出,实际上直接将上述的echo 1或者echo 0 写成cat就okay了
五、device_create_file
可以在创建驱动时,在创建出来的设备目录下/sys/class/xxx/xxx,新建sysfs文件
1 2 3 4 5 6 7 8 9 10 11 12 13
|
int device_create_file(struct device *dev, const struct device_attribute *attr) { int error = 0; if (dev) error = sysfs_create_file(&dev->kobj, &attr->attr); return erro
}
|