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), "%sn", 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功能也会失败。
- spring设置全局异常处理器
- discuz论坛apache日志hadoop大数据分析项目:hive以及hbase是如何入库以及代码实现
- 【Golang语言社区】前端编程- 从零开始开发一款H5小游戏(一) 重温canvas的基础用法
- 今天聊聊分布式锁 No.86
- 【JS游戏编程基础】关于js里的this关键字的理解
- 【算法】随机森林算法
- 【Golang语言社区--H5编程】smoke.js
- GO语言标准库概览
- Golang测试技术
- 安装Python时遇到如下问题,解决方案
- spring使用Email邮件系统
- discuz论坛apache日志hadoop大数据分析项目:清洗数据核心功能解说及代码实现
- mybatis 对于基本类型数据传值的问题
- Guava------------Cache使用方法
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- PHP DB 数据库连接类定义与用法示例
- PHP添加PNG图片背景透明水印操作类定义与用法示例
- 浅谈PHPANALYSIS提取关键字
- 详解PHP队列的实现
- PHP lcfirst()函数定义与用法
- Qt音视频开发38-USB摄像头解码linux方案
- python3 简单实现组合设计模式
- 基于django2.2连oracle11g解决版本冲突的问题
- 浅谈php使用curl模拟多线程发送请求
- PHP模型Model类封装数据库操作示例
- 解决django migrate报错ORA-02000: missing ALWAYS keyword
- PHP封装的数据库模型Model类完整示例【基于PDO】
- PHP的简单跳转提示的实现详解
- PHP多进程通信-消息队列使用
- PHP implode()函数用法讲解