DEVICE_ATTR设置设备属性

DEVICE_ATTR设置设备属性

为了在sysfs下生成可控节点,方便上层调用。

sysfs是一个基于RAM的文件系统,它和Kobject一起,可以将Kernel的数据结构导出到用户空间,以文件目录结构的形式,提供对这些数据结构(以及数据结构的属性)的访问支持。Linux设备模型(4)_sysfs

原型:

#define DEVICE_ATTR(_name, _mode, _show, _store) struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)

类似的还有DRIVER_ATTRBUS_ATTRCLASS_ATTR区别就是,DEVICE_ATTR对应的文件在/sys/devices/目录中对应的device下面。而其他几个分别在driverbusclass中对应的目录下。(待确认)

我实际测试,用DEVICE_ATTR增加的I2C设备,节点是在/sys/bus/i2c/devices/0-0060/fm1288/下的。按照上面的说法,应该fm1288节点应该是在/sys/device

用法:

static ssize_t fm1288_store(struct device *dev,
                  struct device_attribute *attr,
                  const char *buf, size_t count)
{
  struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
  unsigned int reg = 0, write = 0;
    __u16 val = 0;
    int ret;
​
    sscanf(buf,"%x %x %x", &write, &reg, (unsigned int *)&val);//用sscanf读取sysfs写入的值 echo "1 2 3" > fm1288_mode
    fm2018_write(i2c, reg, val);
    fm2018_read(i2c, reg, &val);
}
​
fm1288_showstatic ssize_t fm1288_show(struct device *dev,
                  struct device_attribute *attr,
                  const char *buf, size_t count)
{
    //read mode 
    ssprintf("%d", mode);
}
​
static DEVICE_ATTR(fm1288, S_IWUSR,//模式可以只读0444,只写0222,或者读写都行0666
            fm1288_show, //NULL,不需要该函数可以写NULL
            fm1288_store);
//注意_show和_store的命名一般习惯都是来自name+ _show / _store
static int fm2018_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
{
    struct device *dev = &i2c->dev;
    ret = device_create_file(&i2c->dev, &dev_attr_register);
    if (ret) {
        dev_err(&i2c->dev, "failed to create sysfs files\n");
        return ret;
    }
}
​

 

 

也可以写多个属性,这时,使用sysfs_create_group注册就很方便,代替device_create_file

static DEVICE_ATTR(xtilt,
           S_IRUGO | S_IWUGO, show_tabletXtilt, store_tabletXtilt);
static DEVICE_ATTR(ytilt,
           S_IRUGO | S_IWUGO, show_tabletYtilt, store_tabletYtilt);
​
static struct attribute *aiptek_attributes[] = {
    &dev_attr_xtilt.attr,//名字 dev_attr_name.attr
    &dev_attr_ytilt.attr,
    NULL
};
​
static struct attribute_group aiptek_attribute_group = {
    .attrs  = aiptek_attributes,
};
​
aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
    int err = -ENOMEM;
    err = sysfs_create_group(&intf->dev.kobj, &aiptek_attribute_group);
    if (err) {
        dev_warn(&intf->dev, "cannot create sysfs group err: %d\n",
             err);
        goto fail3;
        }
 fail3: return -1;
}

 

转载于:https://www.cnblogs.com/feixiao5566/p/11061939.html

<think>我们正在讨论Linux设备驱动模型中的sysfs接口,特别是使用DEVICE_ATTR宏来创建设备属性文件。根据引用[1],DEVICE_ATTR宏用于创建一个structdevice_attribute结构体,该结构体定义了sysfs中的一个设备属性。它包含属性名、文件权限以及show和store函数(分别用于读取和写入属性)。用户的问题是如何通过device_attr创建设备的自定义文件路径。但需要注意的是,在sysfs中,设备属性的路径是由设备在sysfs中的位置决定的,通常位于/sys/devices/.../设备目录下。我们不能随意改变这个路径,因为sysfs的结构是固定的(由内核的设备模型决定)。然而,我们可以通过以下方式间接实现“自定义文件路径”:1.在设备目录下创建属性文件(这是标准做法)。2.如果需要在其他位置创建相同的属性,可以使用sysfs的符号链接功能(例如,在/sys/class/...下创建指向设备的符号链接,然后在该链接目录下就会出现相同的属性文件)。因此,我们通常不直接自定义属性文件的路径,而是利用sysfs已有的层次结构。但我们可以通过以下步骤在设备目录下创建一个属性文件:步骤:1.定义show和store函数(如果需要写支持)。2.使用DEVICE_ATTR宏定义设备属性。3.在驱动中,使用device_create_file()函数在设备目录下创建该属性文件。示例代码(基于引用[1]和引用[3]中的信息):```c#include<linux/device.h>//假设我们有一个设备结构体指针structdevice*dev;//定义show函数(读取属性时调用)staticssize_tshow_custom(structdevice*dev,structdevice_attribute*attr,char*buf){//将属性值打印到buf中returnsprintf(buf,"Hello,world!\n");}//定义store函数(写入属性时调用,可选)staticssize_tstore_custom(structdevice*dev,structdevice_attribute*attr,constchar*buf,size_tcount){//从buf中解析用户输入并处理//这里简单示例,不做处理returncount;}//使用DEVICE_ATTR宏定义属性属性名为custom//这将生成一个名为dev_attr_custom的结构体变量staticDEVICE_ATTR(custom,S_IRUGO|S_IWUSR,show_custom,store_custom);//在设备注册后,创建设备属性文件intret=device_create_file(dev,&dev_attr_custom.attr);if(ret){//错误处理}//在设备注销前,移除设备属性文件device_remove_file(dev,&dev_attr_custom.attr);```上述代码在设备对应的sysfs目录下创建一个名为"custom"的文件。权限设置为所有者可写,所有人可读。注意:设备必须已经注册(即已经添加到sysfs中),否则device_create_file会失败。如何访问该文件?假设设备在sysfs中的路径为:/sys/devices/.../my_device,那么属性文件路径就是:/sys/devices/.../my_device/custom。如果我们希望在其他位置(比如在/sys/class/的某个类目录下)也能访问这个属性,我们可以创建一个符号链接。例如,在驱动中,我们可以将设备添加到某个类中,这样在/sys/class/类名/设备名/下就会有指向设备目录的符号链接,属性文件也会出现在那里。总结:我们无法直接改变属性文件在sysfs中的物理路径,但可以通过创建符号链接的方式在其他目录下提供访问。相关问题:1.如何为设备创建多个属性文件?2.如何在sysfs中创建设备的子目录并在其中创建属性文件?3.如何通过设备树(devicetree)描述设备属性?</think>### 通过 device_attr 创建设备自定义文件路径的方法 在 Linux 设备驱动开发中,使用 `DEVICE_ATTR` 宏可以在 sysfs 文件系统中创建设备的自定义属性文件。这些文件通常位于 `/sys/class/类名/设备名/` 路径下,通过以下步骤实现: #### 实现步骤 1. **定义属性操作函数** ```c // 读取属性时调用的函数 static ssize_t custom_attr_show(struct device *dev, struct device_attribute *attr, char *buf) { return sprintf(buf, "Current value: %d\n", your_value); } // 写入属性时调用的函数 static ssize_t custom_attr_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int ret = kstrtoint(buf, 10, &your_value); return ret ? ret : count; } ``` 2. **使用 DEVICE_ATTR 声明属性** ```c static DEVICE_ATTR(custom_path, 0644, custom_attr_show, custom_attr_store); ``` - 参数说明: - `custom_path`: sysfs 中的文件名 - `0644`: 文件权限(用户可读写,组和其他只读) - 最后两个参数:show/store 函数指针 3. **在驱动中注册/注销属性** ```c // 设备探测时注册 int probe(struct platform_device *pdev) { device_create_file(&pdev->dev, &dev_attr_custom_path); } // 设备移除时注销 void remove(struct platform_device *pdev) { device_remove_file(&pdev->dev, &dev_attr_custom_path); } ``` #### 完整示例代码 ```c #include <linux/device.h> static int custom_value = 0; static ssize_t custom_show(struct device *dev, struct device_attribute *attr, char *buf) { return sprintf(buf, "%d\n", custom_value); } static ssize_t custom_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int ret; ret = kstrtoint(buf, 10, &custom_value); return ret ? ret : count; } static DEVICE_ATTR_RW(custom_show); // 等效于 DEVICE_ATTR(custom, 0644, ...) static int my_probe(struct platform_device *pdev) { int err = device_create_file(&pdev->dev, &dev_attr_custom); if (err) { dev_err(&pdev->dev, "Failed to create sysfs file\n"); return err; } return 0; } static int my_remove(struct platform_device *pdev) { device_remove_file(&pdev->dev, &dev_attr_custom); return 0; } ``` #### 访问路径说明 生成的 sysfs 文件路径为: ``` /sys/devices/.../设备名/custom 或 /sys/class/设备类/设备名/custom ``` 可通过命令行访问: ```bash # 读取属性 cat /sys/class/my_class/my_device/custom # 写入属性 echo 42 > /sys/class/my_class/my_device/custom ``` #### 关键说明 1. 使用 `DEVICE_ATTR` 会自动创建 `dev_attr_文件名` 结构体变量 2. 权限参数使用 Unix 权限位掩码: - `S_IRUGO` (0444):所有人可读 - `S_IWUSR` (0200):仅用户可写 3. 在 Linux 5.0+ 中可用简写: - `DEVICE_ATTR_RO`:只读属性 - `DEVICE_ATTR_RW`:读写属性 - `DEVICE_ATTR_WO`:只写属性[^1][^3]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值