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

DEVICE_ATTR的使用的更多相关文章

  1. static DEVICE_ATTR(val, S_IRUGO | S_IWUSR, hello_val_show, hello_val_store); 的作用

    在 老罗的android例程里面有 static DEVICE_ATTR(val, S_IRUGO | S_IWUSR, hello_val_show, hello_val_store); /*读取设 ...

  2. DEVICE_ATTR实例分析

    在内核中, sysfs 属性一般是由 __ATTR 系列的宏来声明的,如对设备的使用 DEVICE_ATTR ,对总线使用 BUS_ATTR ,对驱动使用 DRIVER_ATTR ,对类别(class ...

  3. DEVICE_ATTR

    说道sysfs接口,就不得不提到函数宏 DEVICE_ATTR,原型是 #define DEVICE_ATTR(_name, _mode, _show, _store) \ struct device ...

  4. Linux内核宏DEVICE_ATTR使用

    1.前言 在Linux驱动程序编写中,使用DEVICE_ATTR宏,可以定义一个struct device_attribute设备属性,并使用sysfs的API函数,便可以在设备目录下创建出属性文件, ...

  5. DEVICE_ATTR设置设备属性

    DEVICE_ATTR设置设备属性 为了在sysfs下生成可控节点,方便上层调用. sysfs是一个基于RAM的文件系统,它和Kobject一起,可以将Kernel的数据结构导出到用户空间,以文件目录 ...

  6. Linux设备管理(四)_从sysfs回到ktype

    sysfs是一个基于ramfs的文件系统,在2.6内核开始引入,用来导出内核对象(kernel object)的数据.属性到用户空间.与同样用于查看内核数据的proc不同,sysfs只关心具有层次结构 ...

  7. 基於tiny4412的Linux內核移植--- 中斷和GPIO學習(2)

    作者 彭東林 pengdonglin137@163.com 平臺 tiny4412 ADK Linux-4.4.4 u-boot使用的U-Boot 2010.12,是友善自帶的,爲支持設備樹和uIma ...

  8. linux设备模型

    device_driver和device必须依附总线.总线.驱动.设备最终会落实为sysfs中的一个目录.kobject对应sysfs的一个目录. attribute直接落实sysfs中的一个文件,如 ...

  9. sis9280触摸ic 基于rk3288 的安卓4.4的 多点触摸

    前言:sis提供的驱动ic.基于rk3288的安卓系统.亲眼看到人家完成一次移植.很激动的记下一些东西..虽然我看不懂.其实现在的工作也不需要看懂.叫人协助就好,只需要知道有这个东西. 1linux下 ...

随机推荐

  1. Linux vsftp

    本机环境CentOS-6.6-i386-bin-DVD1.iso安装盘.安装时选择minimal模式.本机IP地址配置为192.168.0.211. 1.查询系统是否已安装了vsftpd [root@ ...

  2. Java之MySql数据库链接

    一 下载MySql驱动包,下载途径很多,随便Google或度娘一下就有,我下载的是mysql-connector-java-5.1.26版本,下载后把它解压到指定路径 二 在Eclipse中新建项目T ...

  3. Struts2的零配置和rest插件

    1. 零配置使用struts2-convention-plugin-2.3.16.jar,rest使用struts2-rest-plugin-2.3.16.jar 1.1 Struts2的conven ...

  4. Java线程池--ThreadPoolExecutor

    一.线程池的处理流程 向线程池提交一个任务后,它的主要处理流程如下图所示: 一个线程从被提交(submit)到执行共经历以下流程: 线程池判断核心线程池里的线程是否都在执行任务,如果不是,则创建一个新 ...

  5. java按行读取txt并按行写入

    IO流想必大家都很熟悉了,本次实现的需求是按行读取文件内容并且按行写入,代码如下: try { String encoding="utf-8"; //设定自己需要的字符编码集 Fi ...

  6. Java Concurrency - Fork/Join Framework

    Normally, when you implement a simple, concurrent Java application, you implement some Runnable obje ...

  7. UML建模——概述

    轻松玩建模 统一建模语言UML快速入门 http://soft.yesky.com/lesson/281/2472281.shtml UML是一种定义良好.易于表达.功能强大且普遍适用的建模语言.它溶 ...

  8. 重建Mac系统的文件打开方式

    /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Ver ...

  9. iOS开发——消息推送跳转

    项目开发用集成是极光推送JPush     这里主要是消息推送过来处理对应界面跳转          同时看到两篇写的不错的相关博客分享一下:      http://www.jianshu.com/ ...

  10. es5 和 es6 class

    // ES5 function User(name,age) { this.name = name; this.age = age; } // 静态方法 User.getClassName = fun ...