【官方文档】
官方描述文档路径为 /linux-4.3/Documentation/driver-model/device.txt
源码路径为 /linux-4.3/include/linux/device.h
【DEVICE_ATTR 说明】
原文描述:
ˉˉˉˉˉˉˉˉˉˉˉˉˉ
Attributes are declared using a macro called DEVICE_ATTR:
#define DEVICE_ATTR(name, mode, show, store)
意思是说,宏 DEVICE_ATTR 用来声明 设备属性文件的 属性(听起来像绕口令)。宏的各参数含义如下:
name 属性文件的名称
mode 属性文件的权限。这个权限值为类似于 0644 这样的 4 位数,分别表示 SUID/GUID+User+Group+Others
show 从该属性文件读数据时调用的函数
源码描述:
ˉˉˉˉˉˉˉˉˉˉˉˉˉ
宏 DEVICE_ATTR 的定义:
#define DEVICE_ATTR(_name, _mode, _show, _store) \
struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
宏 __ATTR(_name, _mode, _show, _store) 的定义:
#define __ATTR(_name, _mode, _show, _store) { \
.attr = {.name = __stringify(_name), .mode = _mode }, \
.show = _show, \
.store = _store, \
}
结构体 device_attribute 的定义:
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_ATTR的作用实际上是在声明并初始化一个 device_attribute结构体。
该结构体名称为 dev_attr_##_name (这里使用了预处理命令中 粘贴操作符 的概念)。
【用处】
使用 DEVICE_ATTR 初始化 device_attribute结构体后, 调用 device_create_file() 函数为设备在 sysfs 中创建一个设备属性文件。
device_create_file() 函数体如下:
/**
* 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)
error = sysfs_create_file(&dev->kobj, &attr->attr);
return error;
}
【举一反三】
类似的宏还有 DRIVER_ATTR、BUS_ATTR、CLASS_ATTR。
【参考文献】
[1] 《sysfs接口函数的建立_DEVICE_ATTR》
官方描述文档路径为 /linux-4.3/Documentation/driver-model/device.txt
源码路径为 /linux-4.3/include/linux/device.h
【DEVICE_ATTR 说明】
原文描述:
ˉˉˉˉˉˉˉˉˉˉˉˉˉ
Attributes are declared using a macro called DEVICE_ATTR:
#define DEVICE_ATTR(name, mode, show, store)
意思是说,宏 DEVICE_ATTR 用来声明 设备属性文件的 属性(听起来像绕口令)。宏的各参数含义如下:
name 属性文件的名称
mode 属性文件的权限。这个权限值为类似于 0644 这样的 4 位数,分别表示 SUID/GUID+User+Group+Others
show 从该属性文件读数据时调用的函数
store 向该属性文件写数据时调用的函数
如果往底层继续追踪这 4 个参数,会发现他们实际上最后赋值给了结构体 kobject 中的成员 *ktype 所指向的 kobj_type 类型结构体。而 kobj_type 类型结构体中又有 attribute类型结构体 和 sysfs_ops类型结构体,后 2 个结构体中的成员即 name、mode、show、store。
这几个结构体常在设备模型中使用,其在内核中的定义如下:
struct kobject {
const char *name; // 名字
struct list_head entry; // 连接到kset建立层次结构
struct kobject *parent; // 指向父节点,面向对象的层次架构
struct kset *kset;
struct kobj_type *ktype; // 属性文件</span>
struct sysfs_dirent *sd;
struct kref kref; // 引用计数
unsigned int state_initialized:1; // 初始化状态。使用位域进行定义,表示该变量在内存中只占用一个二进制位。
unsigned int state_in_sysfs:1;
unsigned int state_add_uevent_sent:1;
unsigned int state_remove_uevent_sent:1;
unsigned int uevent_suppress:1;
};
struct kobj_type {
void (*release)(struct kobject *kobj); // 用于释放 kobject 占用的资源
const struct sysfs_ops *sysfs_ops; // 提供属性文件的方法
struct attribute **default_attrs; // 用于保存类型属性列表(指针的指针)
const struct kobj_ns_type_operations *(*child_ns_type)(struct kobject *kobj);
const void *(*namespace)(struct kobject *kobj);
};
struct sysfs_ops {
ssize_t (*show)(struct kobject *, struct attribute *,char *); //数据读取
ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t); //数据保存
};
struct attribute {
const char *name; // 属性的名字( 在 kobject 的 sysfs 目录中显示)
struct module *owner; // 指向模块的指针( 如果存在), 此模块负责实现这个属性
mode_t mode; // 属性文件的访问权限,例如S_IRUGO 为只读属性等等。在 <linux/stat.h> 中定义
};
源码描述:
ˉˉˉˉˉˉˉˉˉˉˉˉˉ
宏 DEVICE_ATTR 的定义:
#define DEVICE_ATTR(_name, _mode, _show, _store) \
struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
宏 __ATTR(_name, _mode, _show, _store) 的定义:
#define __ATTR(_name, _mode, _show, _store) { \
.attr = {.name = __stringify(_name), .mode = _mode }, \
.show = _show, \
.store = _store, \
}
结构体 device_attribute 的定义:
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_ATTR的作用实际上是在声明并初始化一个 device_attribute结构体。
该结构体名称为 dev_attr_##_name (这里使用了预处理命令中 粘贴操作符 的概念)。
【用处】
使用 DEVICE_ATTR 初始化 device_attribute结构体后, 调用 device_create_file() 函数为设备在 sysfs 中创建一个设备属性文件。
device_create_file() 函数体如下:
/**
* 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)
error = sysfs_create_file(&dev->kobj, &attr->attr);
return error;
}
【举一反三】
类似的宏还有 DRIVER_ATTR、BUS_ATTR、CLASS_ATTR。
【参考文献】
[1] 《sysfs接口函数的建立_DEVICE_ATTR》