DEVICE_ATTR的使用

使用DEVICE_ATTR,可以在sys fs中添加“文件”,通过修改该文件内容,可以实现在运行过程中动态控制device的目的。

类似的还有DRIVER_ATTR,BUS_ATTR,CLASS_ATTR。

这几个东东的区别就是,DEVICE_ATTR对应的文件在/sys/devices/目录中对应的device下面。

而其他几个分别在driver,bus,class中对应的目录下。

这次主要介绍DEVICE_ATTR,其他几个类似。

在documentation/driver-model/Device.txt中有对DEVICE_ATTR的详细介绍,这儿主要说明使用方法。

先看看DEVICE_ATTR的原型:

DEVICE_ATTR(_name, _mode, _show, _store)

_name:名称,也就是将在sys fs中生成的文件名称。

_mode:上述文件的访问权限,与普通文件相同,UGO的格式。

_show:显示函数,cat该文件时,此函数被调用。

_store:写函数,echo内容到该文件时,此函数被调用。

看看我们怎么填充这些要素:

名称可以随便起一个,便于记忆,并能体现其功能即可。

模式可以为只读0444,只写0222,或者读写都行的0666。当然也可以对User\Group\Other进行区别。

显示和写入函数就需要实现了。

显示函数的一般实现:

static ssize_t xxx_show(struct device *dev,

struct device_attribute *attr, char *buf)

{

return scnprintf(buf, PAGE_SIZE, "%d\n", dma_dump_flag);

}

实现相对简单,调用了个很阳春的scnprintf,把数据放到buf中,就算大功告成了。

至于buf中的内容怎么显示出来,这个先略过。

写入函数的一般实现:

static ssize_t xxx_store(struct device *dev,

struct device_attribute *attr, const char *buf, size_t count)

{

unsigned long num;

if (strict_strtoul(buf, 0, &num))

return -EINVAL;

if (num < 0)

return -EINVAL;

mutex_lock(&xxx_lock);

dma_dump_flag = num;

mutex_unlock(&xxx_lock);

return count;

}

也挺直白,就不细说了。

其中加了个lock进行互斥。

函数名中的后缀_show和_store当然不是必须的。

只是便于标识。

DEVICE_ATTR的定义例子:

static DEVICE_ATTR(xxx, 0666, xxx_show, xxx_store);

该代码可以防止文件的任何位置,只要别引起编译错误!

是不是这样就搞定了?

当然没有,还需要调用函数device_create_file来传教sys fs中的文件。

调用方法:

device_create_file(&pdev->dev, &dev_attr_xxx);

文件不是创建在某个device目录下么,pdev->dev就是该device。

dev_attr_xxx就是在xxx前加上dev_attr_,好像是废话,不过现实就是这样。

开始还找了半天,dev_attr_xxx在哪儿定义?

最终发现这儿就是它唯一出现的地方。

device_create_file的调用例子:

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

if (ret != 0) {

dev_err(&pdev->dev,

"Failed to create xxx sysfs files: %d\n", ret);

return ret;

}

这个代码最好放在device的probe函数中。

原因么,在documentation/driver-model/Device.txt中有说明。

下面看看DEVICE_ATTR的定义:

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

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

dev_attr_##_name!!!!!

终于找到dev_attr_xxx定义的地方了!

#define __ATTR(_name,_mode,_show,_store) { \

.attr = {.name = __stringify(_name), .mode = _mode }, \

.show = _show,     \

.store = _store,     \

}

device_attribute定义:

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_ATTR的功能就是定义一个device_attribute结构体对象。

device_create_file利用该对象在device下创建文件。

/**

* device_create_file - create sysfs attribute file for device.

* @dev: device.

* @attr: device attribute descriptor.

*/

int device_create_file(struct device *dev,

const struct device_attribute *attr)

{

int error = 0;

if (dev)

error = sysfs_create_file(&dev->kobj, &attr->attr);

return error;

}

/**

* sysfs_create_file - create an attribute file for an object.

* @kobj: object we're creating for.

* @attr: attribute descriptor.

*/

int sysfs_create_file(struct kobject * kobj, const struct attribute * attr)

{

BUG_ON(!kobj || !kobj->sd || !attr);

return sysfs_add_file(kobj->sd, attr, SYSFS_KOBJ_ATTR);

}

sd的类型为struct sysfs_dirent。

/*

* sysfs_dirent - the building block of sysfs hierarchy.  Each and

* every sysfs node is represented by single sysfs_dirent.

*

* As long as s_count reference is held, the sysfs_dirent itself is

* accessible.  Dereferencing s_elem or any other outer entity

* requires s_active reference.

*/

struct sysfs_dirent {

atomic_t  s_count;

atomic_t  s_active;

#ifdef CONFIG_DEBUG_LOCK_ALLOC

struct lockdep_map dep_map;

#endif

struct sysfs_dirent *s_parent;

struct sysfs_dirent *s_sibling;

const char  *s_name;

const void  *s_ns; /* namespace tag */

union {

struct sysfs_elem_dir  s_dir;

struct sysfs_elem_symlink s_symlink;

struct sysfs_elem_attr  s_attr;

struct sysfs_elem_bin_attr s_bin_attr;

};

unsigned int  s_flags;

unsigned short  s_mode;

ino_t   s_ino;

struct sysfs_inode_attrs *s_iattr;

};

int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr,

int type)

{

return sysfs_add_file_mode(dir_sd, attr, type, attr->mode);

}

int sysfs_add_file_mode(struct sysfs_dirent *dir_sd,

const struct attribute *attr, int type, mode_t amode)

{

umode_t mode = (amode & S_IALLUGO) | S_IFREG;

struct sysfs_addrm_cxt acxt;

struct sysfs_dirent *sd;

int rc;

// 分配空间,并初始化部分成员。

sd = sysfs_new_dirent(attr->name, mode, type);

if (!sd)

return -ENOMEM;

sd->s_attr.attr = (void *)attr;

/*

* Initialize a lock instance's lock-class mapping info:

*/

sysfs_dirent_init_lockdep(sd);

/**

* sysfs_addrm_start - prepare for sysfs_dirent add/remove

* @acxt: pointer to sysfs_addrm_cxt to be used

* @parent_sd: parent sysfs_dirent

*

* This function is called when the caller is about to add or

* remove sysfs_dirent under @parent_sd.  This function acquires

* sysfs_mutex.  @acxt is used to keep and pass context to

* other addrm functions.

*

* LOCKING:

* Kernel thread context (may sleep).  sysfs_mutex is locked on

* return.

*/

sysfs_addrm_start(&acxt, dir_sd);

/**

* sysfs_add_one - add sysfs_dirent to parent

* @acxt: addrm context to use

* @sd: sysfs_dirent to be added

*

* Get @acxt->parent_sd and set sd->s_parent to it and increment

* nlink of parent inode if @sd is a directory and link into the

* children list of the parent.

*

* This function should be called between calls to

* sysfs_addrm_start() and sysfs_addrm_finish() and should be

* passed the same @acxt as passed to sysfs_addrm_start().

*

* LOCKING:

* Determined by sysfs_addrm_start().

*

* RETURNS:

* 0 on success, -EEXIST if entry with the given name already

* exists.

*/

rc = sysfs_add_one(&acxt, sd);

/**

* sysfs_addrm_finish - finish up sysfs_dirent add/remove

* @acxt: addrm context to finish up

*

* Finish up sysfs_dirent add/remove.  Resources acquired by

* sysfs_addrm_start() are released and removed sysfs_dirents are

* cleaned up.

*

* LOCKING:

* sysfs_mutex is released.

*/

sysfs_addrm_finish(&acxt);

if (rc)

sysfs_put(sd);

return rc;

}

基本上知道是怎么回事了。

暂时先到这,就不再深入了。

linux device attr,DEVICE_ATTR的使用相关推荐

  1. The Linux device model

    /sys和 /dev的疑问 1./dev 下放的是设备文件,是由应用层mknod创建的文件.假设底层驱动对mknod的设备号有相应的驱动,如open等函数.那么应用层open "/dev/* ...

  2. 1.the linux device model--kobject kset学习笔记

    http://blog.chinaunix.net/uid-22547469-id-4590385.html?utm_source=jiancool Linux设备模型就是一栋规模宏大的建筑,为了构建 ...

  3. Linux device tree 简要笔记

    第一.DTS简介      在嵌入式设备上,可能有不同的主板---它们之间差异表现在主板资源不尽相同,比如I2C.SPI.GPIO等接口定义有差别,或者是Timer不同,等等.于是这就产生了BSP的一 ...

  4. linux device结构体,struct device结构体

    一.定义: linux/include/linux/device.h struct device { struct klist     klist_children; struct klist_nod ...

  5. Linux Device和Driver注册过程,以及Probe的时机

    Linux 2.6的设备驱动模型中,所有的device都是通过Bus相连.device_register() / driver_register()执行时通过枚举BUS上的Driver/Device来 ...

  6. Android 驱动开发(14)---深入学习Linux Device Tree

    深入学习Linux Device Tree 这个世界需要的是全力以赴,战胜他人先战胜子自己!! Linux Device Tree可描述的信息包括: cpu的数量和类型 内存基地址和大小 总线 外设 ...

  7. Linux rm -rf 之rm: cannot remove `linux': Device or resource busy

    2017年1月19日,清理linux服务器上一目录时出现灵异事件,居然有rm -rf不能删除的东西,排除用户进程占用,但是最后我还是把它给删掉了.     处理过程如下: [oracle@se31 ~ ...

  8. 分享《Essential Linux Device Drivers》中文版高清电子版

    新浪微博 @宋宝华Barry 在@微盘 分享了 Prentice.Hall出版社<Essential.Linux.Device.Drivers>中文版高清电子版 "宋宝华_精通L ...

  9. Linux中SDIO命令,linux device driver之sdio驱动编程分享

    linux device driver之sdio驱动编程分享 闯客网 • 2018-12-19 • 技术交流 [p=26, null, left]先谈谈如何写linux驱动:[/p]- 在驱动模块初始 ...

最新文章

  1. TCP服务器/客户端实例(C/C )
  2. 机器人动力学与控制_力控制与位置控制的区别
  3. 翻转链表python递归_Python实现链表反转的方法【迭代法与递归法】
  4. java 3%3_Java 代码界 3% 的王者?看我是如何解错这 5 道题的
  5. gVim取消自动备份
  6. c语言tty,1. 终端_C语言_C语言入门-Linux C编程一站式学习
  7. java 数据类型之原码,补码,反码
  8. c++11 多线程编程(三)------ 竞争和互斥锁
  9. 开启Spark history server
  10. 手把手教你配置国内镜像源
  11. chrome扩展程序_如何在20分钟内创建和发布Chrome扩展程序
  12. CopyOnWriteArrayList 有什么特点?
  13. LaTeX积分符号汇总
  14. 推特开发者账号【推特开发者文档系列3】——推特标准接口API的请求频率限制说明
  15. 在Vue中使用 createjs
  16. 雨听 | 英语作文作文万能句型
  17. Java数据结构之二叉树及其源码实现
  18. 网页自适应rem如何适配_rem详解及使用方法
  19. 低代码和无代码开发的4个安全问题
  20. 靶机渗透练习67-Looz

热门文章

  1. 洛谷——P2043 质因子分解
  2. Angular 响应式表单 patchValue和setValue
  3. 东北林业大学c语言期末考试题,东北林业大学 2008年C语言考试试卷及答案.doc
  4. 机器学习入门|线性回归(二)
  5. hbase1.3版本启动流程及优化
  6. hashMap的快速存取
  7. C#笔记14 LINQ
  8. php+5.3.15下载,Rapid PHP2018
  9. css怎么写链接到图片和地址
  10. 你知道 ES6~ES12等叫法是怎么来的吗?