理解 DEVICE_ATTR
DEVICE_ATTR
是 Linux 内核中用于创建设备属性的宏,通常用于 sysfs 文件系统。通过 sysfs,用户空间的程序可以读取或修改内核中的设备属性。DEVICE_ATTR
宏定义在 <linux/device.h>
头文件中,用于声明和定义一个设备属性。
基本语法
DEVICE_ATTR
宏的基本语法如下:
DEVICE_ATTR(_name, _mode, _show, _store);
_name
:属性的名称,会在/sys/
下生成对应的文件。_mode
:文件的访问权限,例如0644
表示用户可读写,组和其他用户只读。_show
:当用户读取该属性时调用的函数。_store
:当用户写入该属性时调用的函数。
使用示例
以下是一个简单的示例,展示如何使用 DEVICE_ATTR
:
#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/uaccess.h>static char my_value[100] = "default";static ssize_t show_my_value(struct device *dev, struct device_attribute *attr, char *buf)
{return sprintf(buf, "%s\n", my_value);
}static ssize_t store_my_value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{strncpy(my_value, buf, sizeof(my_value) - 1);my_value[sizeof(my_value) - 1] = '\0';return count;
}static DEVICE_ATTR(my_value, 0644, show_my_value, store_my_value);static struct device *my_device;static int __init my_module_init(void)
{int ret;my_device = &(some_device); // 需要替换为实际的设备结构体ret = device_create_file(my_device, &dev_attr_my_value);if (ret) {printk(KERN_ERR "Failed to create device file\n");return ret;}return 0;
}static void __exit my_module_exit(void)
{device_remove_file(my_device, &dev_attr_my_value);
}module_init(my_module_init);
module_exit(my_module_exit);
MODULE_LICENSE("GPL");
关键点
show
和store
函数是必须的,分别用于读取和写入属性。如果不需要写入功能,可以将_mode
设置为只读(如0444
),并将_store
设置为NULL
。DEVICE_ATTR
宏会生成一个名为dev_attr_my_value
的结构体变量,其中my_value
是属性的名称。- 使用
device_create_file
和device_remove_file
来创建和删除属性文件。
访问属性
在用户空间,可以通过以下方式访问该属性:
# 读取属性
cat /sys/.../my_value# 写入属性
echo "new_value" > /sys/.../my_value
注意事项
- 确保设备的
struct device
结构体已经正确初始化并注册到内核中。 - 在
store
函数中,必须对用户传入的数据进行验证,防止缓冲区溢出或其他安全问题。 - 如果设备被卸载或移除,务必删除所有创建的属性文件,否则可能导致内核崩溃。
其他变体
除了 DEVICE_ATTR
,Linux 内核还提供了其他类似的宏,例如:
DEVICE_ATTR_RO
:只读属性,无需提供store
函数。DEVICE_ATTR_WO
:只写属性,无需提供show
函数。DEVICE_ATTR_RW
:读写属性,需要提供show
和store
函数。
这些宏的使用方式与 DEVICE_ATTR
类似,但更加简洁。