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

基本上知道是怎么回事了。
暂时先到这,就不再深入了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/469285.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Pytorch神经网络理论篇】 28 DGLGraph图的基本操作(缺一部分 明天补)

同学你好&#xff01;本文章于2021年末编写&#xff0c;获得广泛的好评&#xff01; 故在2022年末对本系列进行填充与更新&#xff0c;欢迎大家订阅最新的专栏&#xff0c;获取基于Pytorch1.10版本的理论代码(2023版)实现&#xff0c; Pytorch深度学习理论篇(2023版)目录地址…

泛型(模拟list)

package Test; import java.util.Arrays; public class genericity<T> { private Object[] t; public genericity() { super(); t new Object[0]; } //增加数据 public void add(T t1) { t Arrays.copyOf(t, t.length 1); t[t.length - 1] t1; } //查询数据 public i…

中断处理的tasklet(小任务)机制-不过如此

中断服务程序一般都是在中断请求关闭的条件下执行的,以避免嵌套而使中断控制复杂化。但是&#xff0c;中断是一个随机事件&#xff0c;它随时会到来&#xff0c;如果关中断的时间太长&#xff0c;CPU就不能及时响应其他的中断请求&#xff0c;从而造成中断的丢失。因此&#xf…

【Pytorch神经网络理论篇】 29 图卷积模型的缺陷+弥补方案

同学你好&#xff01;本文章于2021年末编写&#xff0c;获得广泛的好评&#xff01; 故在2022年末对本系列进行填充与更新&#xff0c;欢迎大家订阅最新的专栏&#xff0c;获取基于Pytorch1.10版本的理论代码(2023版)实现&#xff0c; Pytorch深度学习理论篇(2023版)目录地址…

【Pytorch神经网络实战案例】22 基于Cora数据集实现图注意力神经网络GAT的论文分类

注意力机制的特点是&#xff0c;它的输入向量长度可变&#xff0c;通过将注意力集中在最相关的部分来做出决定。注意力机制结合RNN或者CNN的方法。 1 实战描述 【主要目的&#xff1a;将注意力机制用在图神经网络中&#xff0c;完成图注意力神经网络的结构和搭建】 1.1 实现…

用OC和Swift一起说说二叉树

前言&#xff1a; 一&#xff1a;在计算机科学中&#xff0c;二叉树是每个节点最多有两个子树的树结构。通常子树被称作“左子树”&#xff08;left subtree&#xff09;和“右子树”&#xff08;right subtree&#xff09;。二叉树常被用于实现二叉查找树和二叉堆。二&#xf…

【Pytorch神经网络理论篇】 30 图片分类模型:Inception模型

同学你好&#xff01;本文章于2021年末编写&#xff0c;获得广泛的好评&#xff01; 故在2022年末对本系列进行填充与更新&#xff0c;欢迎大家订阅最新的专栏&#xff0c;获取基于Pytorch1.10版本的理论代码(2023版)实现&#xff0c; Pytorch深度学习理论篇(2023版)目录地址…

mtk pwmlinux timer

pwm控制还是有很多要注意的地方 附上驱动的代码 /** drivers/leds/leds-mt65xx.c** This file is subject to the terms and conditions of the GNU General Public* License. See the file COPYING in the main directory of this archive for* more details.** Hydrodent …

【Pytorch神经网络理论篇】 31 图片分类模型:ResNet模型+DenseNet模型+EffcientNet模型

同学你好&#xff01;本文章于2021年末编写&#xff0c;获得广泛的好评&#xff01; 故在2022年末对本系列进行填充与更新&#xff0c;欢迎大家订阅最新的专栏&#xff0c;获取基于Pytorch1.10版本的理论代码(2023版)实现&#xff0c; Pytorch深度学习理论篇(2023版)目录地址…

CentOS7 编译安装golang和rpm安装golang

编译安装 1、下载golang二进制安装包&#xff1a; https://storage.googleapis.com/golang/go1.9.linux-amd64.tar.gz 2、解压安装包到指定目录&#xff0c;此处以解压到/usr/local目录下为例&#xff1a; 1 tar -C /usr/local -xzf ../packages/go1.8.linux-amd64.tar.gz 3、在…

Class_fileAndroid应用调用方法

java代码调用 fos.write这里面是byte类型的 + private static final String LEDBLPATH="/sys/class/hdyrodent_charger_led/brightness"; + private final void SetChargerLedBrightness(String path,int brightness) + { + try{ + …

【Pytorch神经网络理论篇】 32 PNASNet模型:深层可分离卷积+组卷积+空洞卷积

1 PNASNet模型简介 PNASNet模型是Google公司的AutoML架构自动搜索所产生的模型&#xff0c;它使用渐进式网络架构搜索技术&#xff0c;并通过迭代自学习的方式&#xff0c;来寻找最优网络结构。即用机器来设计机器学习算法&#xff0c;使得它能够更好地服务于用户提供的数据。该…

s5k5e2ya MIPI 摄像头调试

1、驱动移植的话按照我之前的文章来做 驱动里面注意是几路的lane,一般mipi的话是差分信号&#xff0c;2路和4路是比较常见的。2、mipi波形 很明显上面的波形是不正确的。dp dn有一个都成了正弦波了。 首先&#xff0c;我们要找一下正确的波形 正确的波形应该是DP和DN不会同时…

css那些事儿4 背景图像

background:背景颜色&#xff0c;图像&#xff0c;平铺方式&#xff0c;大小&#xff0c;位置 能够显示背景区域即为盒子模型的填充和内容部分&#xff0c;其中背景图像将会覆盖背景颜色。常见的水平或垂直渐变颜色背景通常使用水平或垂直渐变的背景图像在水平或垂直方向平铺&a…

用Android UEventObserver监听内核event

很多时候我们在框架上层需要知道内核中某些事件的状态&#xff0c;用设备的show属性是可以供上层来查询&#xff0c;但是这需要上层设定一个较耗资源的循环。如果用UEventObserver就可以监听内核event&#xff0c;它是android Java层利用uevent与获取Kernel层状态变化的机制。 …

【Pytorch神经网络实战案例】23 使用ImagNet的预训练模型识别图片内容

1 案例基本工具概述 1.1 数据集简介 Imagenet数据集共有1000个类别&#xff0c;表明该数据集上的预训练模型最多可以输出1000种不同的分类结果。 Imagenet数据集是目前深度学习图像领域应用得非常多的一个领域&#xff0c;关于图像分类、定位、检测等研究工作大多基于此数据…

杂谈转载

一、什么是运行时&#xff08;Runtime&#xff09;? 运行时是苹果提供的纯C语言的开发库&#xff08;运行时是一种非常牛逼、开发中经常用到的底层技术&#xff09;二、运行时的作用&#xff1f; 能获得某个类的所有成员变量能获得某个类的所有属性能获得某个类的所有方法交换…

Linux中的工作队列

工作队列(work queue)是Linux kernel中将工作推后执行的一种机制。这种机制和BH或Tasklets不同之处在于工作队列是把推后的工作交由一个内核线程去执行&#xff0c;因此工作队列的优势就在于它允许重新调度甚至睡眠。 工作队列是2.6内核开始引入的机制&#xff0c;在2.6.20之后…

【Pytorch神经网络实战案例】24 基于迁移学习识别多种鸟类(CUB-200数据集)

1 迁移学习 在实际开发中&#xff0c;常会使用迁移学习将预训练模型中的特征提取能力转移到自己的模型中。 1.1 迁移学习定义 迁移学习指将在一个任务上训练完成的模型进行简单的修改&#xff0c;再用另一个任务的数据继续训练&#xff0c;使之能够完成新的任务。 1.1.1 迁…

linux工作队列

这里对Linux的工作队列(work_queue)不做深层次的挖掘&#xff0c;只对如何使用它以及一些简单的结构做简单地介绍。 Linux源代码(3.0.8)中和工作队列(work_queue)相关的结构主要在 include/linux/workqueue.h这个头文件中&#xff0c;这里就不摘抄了。这里就直接给出例子代码…