L4. ATTR节点应用

1.ATTR介绍

应用层与内核驱动层的交互,一般是通过驱动节点的读写来实现。即驱动开发人员在完成驱动设备的创建后,同时会创建对应的节点,且提供节点的访问函数,以便应用层开发调用。驱动提供接口的方法有注册file_operation结构体,另一种方法就是本文要记录的建立ATTR节点。
使用DEVICE_ATTR,可以实现驱动在sys目录自动创建文件,我们只需要实现show和store函数即可。然后在应用层就能通过cat和echo命令来对sys创建出来的文件进行读写驱动设备,实现交互。

2.基本原理概述

2.1 DEVICE_ATTR()

DEVICE_ATTR()定义位于Android/kernel-4.14/include/linux/device.h

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

__ATTR()位于Android/kernel-4.14/include/linux/sysfs.h

#define __ATTR_PREALLOC(_name, _mode, _show, _store) {                  \
   .attr = {.name = __stringify(_name),                                 \
             .mode = SYSFS_PREALLOC | VERIFY_OCTAL_PERMISSIONS(_mode) },\
   .show   = _show,                                                     \
   .store   = _store,                                                   \
}

发现DEVICE_ATTR()只是内核定义的一个宏,使用此宏作用相当于定义并填充了一个device_attribute类型的结构体dev_attr_xx。其中需要注意的是_mode参数表示文件权限,一般是给0664,权限比0664高会报错(也可以用S_IWUSR(用户可写),S_IRUSR(用户可读)等宏代替)。

将DEVICE_ATTR()宏完全展开

#define DEVICE_ATTR(_name, _mode, _show, _store)         \
struct device_attribute dev_attr_##_name = {           \
   .attr = {.name = __stringify(_name),                  \
             .mode = SYSFS_PREALLOC | VERIFY_OCTAL_PERMISSIONS(_mode) },\
   .show   = _show,                                        \
   .store   = _store,                                        \
}

2.2 device_attribute

device_attribute同样定义位于Android/kernel-4.14/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_attribute结构体内包含一个attribute 和 show、store函数。其中show接口实现adb内 cat读取显示功能,store实现的是echo 写入功能。
因此在驱动中,需要实现show、store接口功能。

2.3 device_create_file

在实例完struct device_attribute dev_attr_xx后,需要将此结构体通过device_create_file注册到内核中/sys/bus/platform/devices下。定义在kernel-4.14/drivers/base/core.c

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);

3.实际操作

首先在内核创建一个驱动文件,这里命名为attr_test。
增加节点读接口

/创建ATTR可读节点接口/

static ssize_t show_attr_test(struct device *dev, struct device_attribute *attr, char *buf)
{
int ret = 0;

    ret = snprintf(buf, strlen(global_char), "%s\n", global_char);
printk("%s:%d: Entry %s, buf:%s", __FILE__, __LINE__, __func__, buf);

    return ret;
}

/* 创建ATTR可写节点接口 */

static ssize_t store_attr_test(struct device *dev, struct device_attribute *attr,
             const char *buf, size_t count)
{
    int ret = 0;
   
    memset(global_char, 0x00, sizeof(global_char));
    ret = snprintf(global_char, sizeof(global_char), "%s", buf);
    printk("%s:%d: Entry %s", __FILE__, __LINE__, __func__);

    return ret;
}

填充到结构体dev_attr_attr_test

DEVICE_ATTR(attr_test, 0664, show_attr_test, store_attr_test);

注册到内核中

ret = device_create_file(&pdev->dev, &dev_attr_attr_test);`

注意:在实现show、store时,返回值必须为具体的字符长度,若返回0则会出导致数据传输出现问题,cat、echo功能也会失败。

2020-06-21

记录历经的路,分享个人总结与感悟。欢迎关注公众号“嵌入式漫漫修道路”

嵌入式漫漫修道路

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

拂去尘世尘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值