sysfs_create_group创建sysfs接口

在调试驱动,可能需要对驱动里的某些变量进行读写,或函数调用。可通过sysfs接口创建驱动对应的属性,使得可以在用户空间通过sysfs接口的show和store函数与硬件交互;

Syss接口可通过sysfs_create_group()来创建,如果设备驱动要创建,需要用到函数宏DEVICE_ATTR;

另外总线对应BUS_ATTR、设备驱动对应DRIVER_ATTR、类(class)对应CLASS_ATTR,均在kernel/include/linux/device.h下定义:

 1 //下面的show和store只是简单举例
 2 static ssize_t gpio_show(struct device *d, struct device_attribute*attr, char *buf)
 3 {
 4        printk("gpio_show()\n");
 5        returnpr_info("store\n");
 6 }
 7  
 8 static ssize_t gpio_store(struct device *d, struct device_attribute *attr,const char *buf,size_t count)
 9 {
10        printk("gpio_store()\n");
11        returnpr_info("store\n");
12 }
13  
14 //用DEVICE_ATTR宏创建属性gpio文件,如果show()或是store()没有功能,就以NULL代替
15 static DEVICE_ATTR(gpio, S_IWUSR |S_IRUGO, gpio_show, gpio_store);
16  
17 //属性结构体数组最后一项必须以NULL结尾。
18 static struct attribute *gpio_attrs[] = {
19        &dev_attr_gpio.attr,
20        NULL
21 };

DEVICE_ATTR:

DEVICE_ATTR 的定义DEVICE_ATTR(_name,_mode, _show, _store);可知这里gpio是name,mode是S_IWUSR |S_IRUGO,读操作_show是gpio_show函数,写操作_store 是gpio_store函数;

因为:

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

device_attribute:

1 /* interface for exporting device attributes */
2 struct device_attribute {
3     struct attribute    attr;
4     ssize_t (*show)(struct device *dev, struct device_attribute *attr,
5             char *buf);
6     ssize_t (*store)(struct device *dev, struct device_attribute *attr,
7              const char *buf, size_t count);
8 };

Mode是权限位,在kernel/include/uapi/linux/stat.h;

 1 #define S_IRWXU 00700 //用户可读写和执行
 2 #define S_IRUSR 00400//用户可读
 3 #define S_IWUSR 00200//用户可写
 4 #define S_IXUSR 00100//用户可执行
 5  
 6 #define S_IRWXG 00070//用户组可读写和执行
 7 #define S_IRGRP 00040//用户组可读
 8 #define S_IWGRP 00020//用户组可写
 9 #define S_IXGRP 00010//用户组可执行
10  
11 #define S_IRWXO 00007//其他可读写和执行
12 #define S_IROTH 00004//其他可读
13 #define S_IWOTH 00002//其他可写
14 #define S_IXOTH 00001//其他可执行

device_attribute结构体

为了使对属性的读写变得有意义,一般将attribute结构嵌入到其他数据结构中。子系统通常都会定义自己的属性结构,并且提供添加和删除属性文件的包装函数,比如设备属性结构体定义:

1 /* interface for exporting device attributes */  
2 struct device_attribute {  
3        struct attribute    attr;  
4        ssize_t (*show)(structdevice *dev, struct device_attribute *attr,  
5                      char*buf);  
6        ssize_t (*store)(structdevice *dev, struct device_attribute *attr,  
7                       const char *buf, size_t count);  
8 };

2.     定义attribute属性结构体数组到属性组中:

 1 static const struct attribute_group gpio_attr_grp = {
 2        .attrs = gpio_attrs,
 3 }
 4 我们这里只有一个属性结构体数组只有一个成员,可以有多个,比如:
 5 static struct attribute *gpio_keys_attrs[] = {
 6        &dev_attr_keys.attr,
 7        &dev_attr_switches.attr,
 8        &dev_attr_disabled_keys.attr,
 9        &dev_attr_disabled_switches.attr,
10        &dev_attr_test.attr,
11        NULL,
12 };

属性attribute结构体定义:

1 struct attribute {  
2        const char           *name;  
3        umode_t                     mode;  
4 #ifdef CONFIG_DEBUG_LOCK_ALLOC  
5        bool                     ignore_lockdep:1;  
6        struct lock_class_key *key;  
7        struct lock_class_key skey;  
8 #endif  
9 };

创建sysfs接口后,就可以在adb shell 终端查看到和操作接口了。当我们将数据 echo 到接口中时,在用户空间完成了一次 write 操作,对应到 kernel ,调用了驱动中的”store”。当我们cat一个接口时则会调用”show” 。这样就建立了 android 层到 kernel 的桥梁,操作的细节在”show”和”store” 中完成的。

3.     创建属性文件的sysfs接口:

1 ret = sysfs_create_group(&pdev->dev.kobj,&gpio_attr_grp);
2 sysfs_create_group()在kobj目录下创建一个属性集合,并显示集合中的属性文件。如果文件已存在,会报错。
3  
4 //删除接口
5 sysfs_remove_group(&pdev->dev.kobj,&gpio_keys_attr_group);
6 sysfs_remove_group()在kobj目录下删除一个属性集合,并删除集合中的属性文件

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏ShaoYL

内存管理总结-autoreleasePool

3306
来自专栏Kirito的技术分享

JAVA 拾遗--Future 模式与 Promise 模式

写这篇文章的动机,是缘起于微信闲聊群的一场讨论,粗略整理下,主要涉及了以下几个具体的问题: 同步,异步,阻塞,非阻塞的关联及区别。 JAVA 中有 callb...

2K7
来自专栏我叫刘半仙

原荐Spring AOP是什么?你都拿它做什么?

         对于最近博主最近写博客的兴致大发,我也在思考:为什么而写博客?在互联网时代,无论你是牛人大咖,还是小白菜鸟,都有发表自己看法的权利。无论你是对...

3034
来自专栏blog.csdn.net/LHWorld

【Linux篇】--awk的使用

awk是一个强大的文本分析工具。相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。 简单来说awk就是把文件逐行的读入,(空格...

1232
来自专栏菩提树下的杨过

java:使用匿名类直接new接口

java中的匿名类有一个倍儿神奇的用法,见下面代码示例: 1 package contract; 2 3 public interface ISay { 4 ...

1999
来自专栏牛肉圆粉不加葱

[Spark源码剖析]Task的调度与执行源码剖析

一个Spark Application分为stage级别和task级别的调度,stage级别的调度已经用[DAGScheduler划分stage]和[DAGSc...

1272
来自专栏犀利豆的技术空间

徒手撸框架--实现 RPC 远程调用

微服务已经是每个互联网开发者必须掌握的一项技术。而 RPC 框架,是构成微服务最重要的组成部分之一。趁最近有时间。又看了看 dubbo 的源码。dubbo 为了...

1032
来自专栏青玉伏案

iOS逆向工程之Hopper中的ARM指令

虽然前段时间ARM被日本软银收购了,但是科技是无国界的,所以呢ARM相关知识该学的学。现在看ARM指令集还是倍感亲切的,毕竟大学里开了ARM这门课,并且做了不少...

2607
来自专栏進无尽的文章

简述OC语言

对于一门语言的学习是需要时间领悟的,而对于一些原理性的问题,我们需要清楚其核心思想,知其然而知其所以然,这样才能有利于自己的后续发展。本文只是简述,没有面面具到...

1162
来自专栏小樱的经验随笔

堆和栈的区别

一、预备知识—程序的内存分配 一个由c/C++编译的程序占用的内存分为以下几个部分 1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量...

3449

扫码关注云+社区