创建设备文件_使用DEVICE_ATTR实例分析

在android中操作驱动时,很多时候都是使用的sysfs文件系统来进行直接操作。即通过操作一个节点文件,直接实现对kernel层的数据操作。这个时候,就不得不提一个宏:DEVICE_ATTR。

DEVICE_ATTR宏定义在include/linux/device.h中,所以一般需要添加头文件:
#include <linux/device.h>

函数原型是:

#define DEVICE_ATTR(_name, _mode, _show, _store) \

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

DEVICE_ATTR 宏声明有四个参数,分别是名称(_name)、权限位(_mode:一般使用S_IRUGO | S_IWUSR或者0664)、读函数(_show)、写函数(_store)。

其中读函数和写函数是读写功能函数的函数名。调用DEVICE_ATTR生成的对应的文件在/sys/devices/目录中对应的device下面。

代码主要实现过程如下:

static ssize_t test_czd_show(struct device *dev,struct device_attribute *attr, char *buf) //读函数的封装定义,自己根据需要添加相应的操作
{
return sprintf(buf, “%s\n”, “czd:test code”);
}

static ssize_t test_czd_store(struct device *dev,struct device_attribute *attr,const char *buf, size_t count) //写函数的封装定义,自己根据需要添加相应的操作
{
return count;
}

static DEVICE_ATTR(test_czd, S_IRUGO | S_IWUSR, test_czd_show, test_czd_store);//创建设备节点文件test_czd

当你想要实现的接口名字是test_czd的时候,需要实现结构体struct attribute *dev_attrs[],其中成员变量的名字必须是&dev_attr_test_czd.attr,即&dev_attr_xxxx.attr,xxxx表示节点名字
static struct attribute *dev_attrs[] = {
&dev_attr_test_czd.attr,
NULL,
};

然后再封装:
static struct attribute_group dev_attr_group = {
.attrs = dev_attrs,
};

然后在probe函数中调用:sysfs_create_group(&client->dev.kobj, &dev_attr_group);//创建接口sysfs

在remove函数中调用:sysfs_remove_group(&client->dev.kobj, &dev_attr_group);//在remove中移除接口sysfs

原理:当我们将数据echo到接口中时,在上层实际上完成了一次write操作,对应到kernel调用了驱动中的store。同理,当我们cat一个接口时则会调用show。到这里,

只是简单的建立了android层到kernel的桥梁,真正实现对硬件操作的,还是在show和store中完成的。

如何使用:
通过adb连接,在shell下输入以下:

1、cd到对应目录,cd /sys/devices/platform/xxxx //xxxx表示对应的设备,然后cat test_czd 此时可以读出该接口的信息,也就是执行test_czd_show这个函数

2、cd到对应目录,cd /sys/devices/platform/xxxx //xxxx表示对应的设备,然后echo 01 > test_czd 这样就执行test_czd_store

当然_ATTR还有一些同类的宏函数,我们应该根据需要来使用不同的宏函数:

对设备的使用:DEVICE_ATTR

对驱动使用:DRIVER_ATTR

对总线使用:BUS_ATTR

对类别 (class) 使用:CLASS_ATTR

---------- 爱生活,爱安卓,爱Linux ----------

猜你喜欢

转载自blog.csdn.net/qq_30624591/article/details/85273930