为驱动创建自定义的 sysfs 属性文件,实现读写回调
Sysfs是一个虚拟文件系统,它提供了内核对象、设备、驱动和模块的信息。通过Sysfs,用户空间可以与内核空间进行交互,读取或设置驱动参数。
下面是一个简单的示例,展示如何创建具有读写功能的sysfs属性:
#include <linux/device.h>
#include <linux/sysfs.h>
static int my_value = 0;
// 读取回调函数
static ssize_t my_value_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
return sprintf(buf, "%d\n", my_value);
}
// 写入回调函数
static ssize_t my_value_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
int ret;
ret = kstrtoint(buf, 10, &my_value);
if (ret < 0)
return ret;
return count;
}
// 定义设备属性
static DEVICE_ATTR_RW(my_value);
在驱动探测函数中创建属性文件,在移除函数中删除它:
static int my_driver_probe(struct device *dev)
{
int err;
// 创建属性文件
err = device_create_file(dev, &dev_attr_my_value);
if (err) {
dev_err(dev, "无法创建sysfs属性\n");
return err;
}
return 0;
}
static void my_driver_remove(struct device *dev)
{
// 删除属性文件
device_remove_file(dev, &dev_attr_my_value);
}
属性类型 | 宏定义 | 描述 |
---|---|---|
只读 | DEVICE_ATTR_RO | 只能读取的属性 |
只写 | DEVICE_ATTR_WO | 只能写入的属性 |
读写 | DEVICE_ATTR_RW | 可读可写的属性 |
提示: 确保属性操作是线程安全的,特别是在多处理器系统中。
注意: 不要在show和store函数中执行耗时操作,这会阻塞用户空间进程。
下面是一个完整的驱动示例,展示了如何创建和使用sysfs属性:
#include <linux/module.h>
#include <linux/device.h>
#include <linux/slab.h>
static struct kobject *example_kobj;
static int example_value = 100;
static ssize_t example_show(struct kobject *kobj,
struct kobj_attribute *attr,
char *buf)
{
return sprintf(buf, "%d\n", example_value);
}
static ssize_t example_store(struct kobject *kobj,
struct kobj_attribute *attr,
const char *buf, size_t count)
{
int ret;
ret = kstrtoint(buf, 10, &example_value);
if (ret < 0)
return ret;
return count;
}
static struct kobj_attribute example_attr =
__ATTR(example_value, 0664, example_show, example_store);
static int __init example_init(void)
{
int ret;
example_kobj = kobject_create_and_add("example", kernel_kobj);
if (!example_kobj)
return -ENOMEM;
ret = sysfs_create_file(example_kobj, &example_attr.attr);
if (ret)
kobject_put(example_kobj);
return ret;
}
static void __exit example_exit(void)
{
kobject_put(example_kobj);
}
module_init(example_init);
module_exit(example_exit);
MODULE_LICENSE("GPL");