__ATTR填充结构体:kernel-4.9/include/linux/sysfs.h
#define __ATTR(_name, _mode, _show, _store) { \
.attr = {.name = __stringify(_name), \
.mode = VERIFY_OCTAL_PERMISSIONS(_mode) }, \
.show = _show, \
.store = _store, \
}
DEVICE_ATTR定义并初始化结构体:kernel-4.9/include/linux/device.h
#define DEVICE_ATTR(_name, _mode, _show, _store) \
struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
DEVICE_ATTR定义的结构体:kernel-4.9/include/linux/device.h
/* interface for exporting device attributes */
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);
};
device_create_file创建文件节点,最终调用的还是sysfs_create_file(用于创建一个节点):
:drivers/base/core.c
/**
* device_create_file - create sysfs attribute file for device.
* @dev: device.
* @attr: device attribute descriptor.
*/
int device_create_file(struct device *dev,
const struct device_attribute *attr)
{
int error = 0;
if (dev) {
WARN(((attr->attr.mode & S_IWUGO) && !attr->store),
"Attribute %s: write permission without 'store'\n",
attr->attr.name);
WARN(((attr->attr.mode & S_IRUGO) && !attr->show),
"Attribute %s: read permission without 'show'\n",
attr->attr.name);
error = sysfs_create_file(&dev->kobj, &attr->attr);
}
return error;
}
EXPORT_SYMBOL_GPL(device_create_file);
sysfs_create_files第二个参数是一个二维数组,所以可以创建多个节点:
:fs/sysfs/file.c
int sysfs_create_files(struct kobject *kobj, const struct attribute **ptr)
{
int err = 0;
int i;
for (i = 0; ptr[i] && !err; i++)
err = sysfs_create_file(kobj, ptr[i]);
if (err)
while (--i >= 0)
sysfs_remove_file(kobj, ptr[i]);
return err;
}
EXPORT_SYMBOL_GPL(sysfs_create_files);
kernel4.9下面有中文注册的文档
./Documentation/zh_CN/filesystems/sysfs.txt`
一个demo:只用于参考:
//debug part
static ssize_t fs_demo_show(struct device* cd,
struct device_attribute *attr, char* buf)
{
int len = 0;
len += snprintf(buf+len, PAGE_SIZE-len, "useg: only a attr fs demo show\n");
return len;
}
static ssize_t fs_demo_store(struct device* cd,
struct device_attribute *attr,const char* buf, size_t len)
{
int databuf[2];
if(2 == sscanf(buf,"%d %d",&databuf[0], &databuf[1])){
unsigned char cmd_tmp[2] = {(unsigned char)databuf[0],0};
....
}
return len;
}
static DEVICE_ATTR(fs_demo, 0664, fs_demo_show, fs_demo_store);
//dev_attr_#name;
static int fs_demo_probe(struct platform_devvice *dev)
{
int device_create_file(struct device *device,
const struct device_attribute *entry); //在fs_demo前面加上dev_attr_合并成dev_attr_fs_demo
//&dev_attr_fs_demo就是entry
}