DEVICE_ATTR

深入解析DEVICE_ATTR_RW:Linux内核中的可读写属性实现 本文深入解析了Linux内核中的DEVICE_ATTR_RW宏,详细介绍了其作为内核与用户空间桥梁的实现原理及使用方法。通过实例演示如何创建可读写属性,并提供了实战中的避坑指南和性能优化建议,帮助开发者高效利用sysfs接口进行设备驱动开发。 阅读详情

sysfs接口函数的建立_DEVICE_ATTR  

2012-05-09 11:36:46|  分类:linux文件系统 |  标签:device_attr  sysfs接口函数  |字号大中小 订阅

说道sysfs接口,就不得不提到函数宏 DEVICE_ATTR,原型是

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

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

函数宏DEVICE_ATTR内封装的是__ATTR(_name,_mode,_show,_stroe)方法

_show:表示的是读方法,

_stroe表示的是写方法。

 

当然_ATTR不是独生子女,他还有一系列的姊妹__ATTR_RO宏只有读方法,__ATTR_NULL等等

如对设备的使用        DEVICE_ATTR   

对驱动使用               DRIVER_ATTR

对总线使用               BUS_ATTR 

对类别 (class) 使用  CLASS_ATTR

这四个高级的宏来自于<include/linux/device.h> 

DEVICE_ATTR  宏声明有四个参数,分别是名称、权限位、读函数、写函数。其中读函数和写函数是读写功能函数的函数名。

如果你完成了DEVICE_ATTR函数宏的填充,下面就需要创建接口了

例如:

    static DEVICE_ATTR(polling, S_IRUGO | S_IWUSR, show_polling, set_polling);
    static struct attribute *dev_attrs[] = {
            &dev_attr_polling.attr,
            NULL,
    };

当你想要实现的接口名字是polling的时候,需要实现结构体struct attribute *dev_attrs[]

其中成员变量的名字必须是&dev_attr_polling.attr

然后再封装

    static struct attribute_group dev_attr_grp = {
            .attrs = dev_attrs,
    };

在利用 sysfs_create_group(&pdev->dev.kobj, &dev_attr_grp);创建接口

       通过以上简单的三个步骤,就可以在adb shell 终端查看到接口了。当我们将数据 echo 到接口中时,在上层实际上完成了一次 write 操作,对应到 kernel ,调用了驱动中的 “store”。同理,当我们cat 一个 接口时则会调用 “show” 。到这里,只是简单的建立了 android 层到 kernel 的桥梁,真正实现对硬件操作的,还是在 "show" 和 "store" 中完成的。


       其实呢?!用个proc文件系统的就知道,这个就和proc中的write和read一样的,以我的理解:proc有点老了,以后肯定会大量使用attribute,proc好比是Windows XP,attribute就像是Windows Seven



###############################################################

为了更好地了解kobject的层次关系,有必要了解一下这种层次关系的表现机制:sysfs。本文简单地学习了一下sysfs,大部分内容来自内核文档sysfs.txt。好了,开始我们的学习之旅,呵呵。

 

何为sysfs

    sysfs是一种基于ram的文件系统,它提供了一种用于向用户空间展现内核空间里的对象、属性和链接。sysfs与kobject层次紧密相连,它将kobject层次关系表现出来,使得用户空间可以看见这些层次关系。

    在控制台输入命令“mount -t sysfs sysfs /sys”,就可以在/sys目录下看到这些层次关系了。

 

目录的创建

    对于每个注册到系统的kobject,在sysfs中都有一个目录来展现它,这个目录(AA)会作为某个目录(A)的子目录而被创建,我们知道目录AA代表kobject,那么目录A则代表kobject->parent,显示这种目录层次关系可以很好地向用户展现kobject层次结构。在sysfs中位于顶层的那些目录,分别代表着不同的子系统,每个新加入的kobject都应该归属于某一个子系统。

    sysfs会把目录所代表的kobject存储在目录的dentry结构的d_fsdata字段,这样当文件打开和关闭的时候,sysfs可以直接对kobject做引用计数。

 

属性

    在sysfs中,kobject的属性表现为一个普通的文件。sysfs将文件的I/O操作重定向到那些为该属性定义的方法,提供了一种读写属性的机制。

     属性应该表现为ASCII文本文件,并且最好每个文件只包含一个值。当然,每个文件仅包含一个值可能会有害于效率,所以如果一个文件包含某种类型的数据的数组也是被接受的。不建议在一个文件中包含不同数据类型的数据和多行数据。


    属性的定义如下:

    struct attribute {
        char                    * name;
        struct module  *owner;
        mode_t                  mode;
    };


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

        在kobj所在目录下创建一个属性文件,文件名为attr->name
    void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr);

        将属性文件attr->name从kobj所在目录下移除

 

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

    例如,设备驱动模型为device子系统定义了相应的属性结构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);
    };

 

    int device_create_file(struct device *, struct device_attribute *);

        在/sys/devices/xxx/目录下创建device属性文件
    void device_remove_file(struct device *, struct device_attribute *);

        移除/sys/devices/xxx/目录下的device属性文件

 

    系统提供了一个宏方便定义device属性:

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

  

    其中,__ATTR定义如下:

    #define __ATTR(_name,_mode,_show,_store) { /
     .attr = {.name = __stringify(_name), .mode = _mode }, /
     .show = _show,     /
     .store = _store,     /
    }

   

    例如,定义一个device属性,名为foo,读写该文件的方法分别为show_foo和store_foo:

    static DEVICE_ATTR(foo, S_IWUSR | S_IRUGO, show_foo, store_foo);

    将宏展开为:   

    static struct device_attribute dev_attr_foo = {
            .attr = {
                          .name = "foo",
                          .mode = S_IWUSR | S_IRUGO,

                       },
            .show = show_foo,
            .store = store_foo,
    };

 

子系统特定的回调函数

    当子系统定义一个新的属性类型时,必须实现一组sysfs操作,从而将文件的读写调用(read/write调用)重定向到属性拥有者的show和store方法。

 

    struct sysfs_ops {
        ssize_t (*show)(struct kobject *, struct attribute *, char *);
        ssize_t (*store)(struct kobject *, struct attribute *, const char *);
    };

 

    当读写一个文件时,sysfs将为此类型调用合适的方法,这些方法会将kobject结构和attribute结构转换为合适的指针类型,然后调用与之关联的相关的方法。注意,子系统必须已经为此类型定义好了kobj_type作为此类型的描述符,因为sysfs_ops指针存储在kobj_type中。

    举个例子:  

    #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr)
    #define to_dev(d) container_of(d, struct device, kobj)

    static ssize_t dev_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
    {
        struct device_attribute * dev_attr = to_dev_attr(attr);
        struct device * dev = to_dev(kobj);
        ssize_t ret = 0;

        if (dev_attr->show)
                ret = dev_attr->show(dev, buf);
        return ret;
    }

 

属性的读写

    为了读写属性,当定义属性时,必须指定show和/或者store方法:

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

 

sysfs allocates a buffer of size (PAGE_SIZE) and passes it to the
method. Sysfs will call the method exactly once for each read or
write. This forces the following behavior on the method
implementations:

 

- On read(2), the show() method should fill the entire buffer. 
  Recall that an attribute should only be exporting one value, or an
  array of similar values, so this shouldn't be that expensive.

  This allows userspace to do partial reads and forward seeks
  arbitrarily over the entire file at will. If userspace seeks back to
  zero or does a pread(2) with an offset of '0' the show() method will
  be called again, rearmed, to fill the buffer.

- On write(2), sysfs expects the entire buffer to be passed during the
  first write. Sysfs then passes the entire buffer to the store()
  method. 
  
    当写一个sysfs文件时,用户空间的进程应该先读取整个文件,然后修改希望改变的值,最后将整个缓冲区回写到文件中。

    Attribute method implementations should operate on an identical buffer when reading and writing values.

   

    其他注意事项:

- Writing causes the show() method to be rearmed regardless of current file position.(???)

- 缓冲区的大小应总是为PAGE_SIZE个字节。在i386上,PAGE_SIZE=4096

- show方法应该返回放入缓冲区的字节数,即snprintf的返回值

- show方法应该总是使用snprintf

- store方法应该返回实际使用的字节数,可以使用strlen来得到

- show和/或者store方法可能会出错,所以当失败时,记得返回错误值

- The object passed to the methods will be pinned in memory via sysfs
  referencing counting its embedded object. However, the physical 
  entity (e.g. device) the object represents may not be present. Be 
  sure to have a way to check this, if necessary. (???)
    下面的代码展示了device属性的一个简单的实现:

    static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf)
    {
         return snprintf(buf, PAGE_SIZE, "%s/n", dev->name);
    }

    static ssize_t store_name(struct device * dev, const char * buf)
    {
         sscanf(buf, "%20s", dev->name);
         return strnlen(buf, PAGE_SIZE);
    }

    static DEVICE_ATTR(name, S_IRUGO, show_name, store_name);

    注意,实际应用时,并不允许从用户空间设置设备的名字,这里仅举个例子。

 

sysfs顶层目录结构

    sysfs目录结构展现了内核数据结构之间的关系,顶层目录结构如下:

 

block/
bus/
class/
dev/
devices/
firmware/
net/
fs/

 

    下面捡几个重要的目录进行说明:

    devices目录展现了系统中的设备树,它直接对应于内核中的设备树,即device的层次结构 ;

    bus目录下包含了若干目录,每个目录表示系统中的一个总线,且每个目录下又包含两个子目录:devices、drivers。其中devices子目录下包含系统中发现的device的符号链接,这些符号链接分别指向/sys/devices/xxx目录下对应的目录;drivers子目录下包含特定总线上的那些用于驱动每个设备的驱动程序的目录(可见,一个驱动程序只会出现在某一个特定的总线上);

   

当前接口

    目前sysfs中存在以下接口:
- devices (include/linux/device.h)
    device属性:

    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(_name, _mode, _show, _store);

    属性的创建和移除:

    int device_create_file(struct device *device, struct device_attribute * attr);
    void device_remove_file(struct device * dev, struct device_attribute * attr);


- bus drivers (include/linux/device.h)
    bus属性:

    struct bus_attribute {
        struct attribute        attr;
        ssize_t (*show)(struct bus_type *, char * buf);
        ssize_t (*store)(struct bus_type *, const char * buf);
    };

    属性的声明:

    BUS_ATTR(_name, _mode, _show, _store)

    属性的创建和移除:

    int bus_create_file(struct bus_type *, struct bus_attribute *);
    void bus_remove_file(struct bus_type *, struct bus_attribute *);


- device drivers (include/linux/device.h)
    driver属性:

    struct driver_attribute {
        struct attribute        attr;
        ssize_t (*show)(struct device_driver *, char * buf);
        ssize_t (*store)(struct device_driver *, const char * buf,
                         size_t count);
    };

    属性的声明:

    DRIVER_ATTR(_name, _mode, _show, _store)

    属性的创建和移除:

    int driver_create_file(struct device_driver *, struct driver_attribute *);
    void driver_remove_file(struct device_driver *, struct driver_attribute *);

Linux内核--DEVICE_ATTR 内核版本:v4.14 简介 在我们调试或者使用内核驱动时,有时候需要动态设置或读取驱动的参数或属性,此时我们就可以使用DEVICE_ATTR创建一个节点,通过在这个节点写入或者读取来实现上诉功能。 DEVICE_ATTR定义 #define DEVICE_ATTR(_name, _mode, _show, _store) _name : 定义的节点名称 _mode : 节点访问权限,类似于0644 _show : cat节点时的回调函数 _store : echo节点时候的回调函数 内核定义 #defin 阅读详情

相关推荐

DEVICE_ATTR使用

1. 作用 使用DEVICE_ATTR往sysfs中为device添加“属性文件”,并对该文件添加相关操作,从而实现运行过程中动态控制device。 2. 一些定义 首先看一下与DEVICE_ATTR相关的宏定义,定义位置在kernel/include/linux/device.h中。 #define DEVICE_ATTR(_name, _mode, _show, _store) \ ...

阙靖的博客 1259

sysfs Linux-DEVICE_ATTR()介绍及使用示例

1.介绍 使用DEVICE_ATTR,可以实现驱动在sys目录自动创建文件,我们只需要实现show和store函数即可. 然后在应用层就能通过cat和echo命令来对sys创建出来的文件进行读写驱动设备,实现交互. 2.DEVICE_ATTR()宏定义 DEVICE_ATTR()定义位于include/linux/device.h中,定义如下所示: #define DEVICE_ATTR(_name, _mode, _show, _store) \ struct device_attribute d

Wang20122013的博客 9661

深入剖析 Linux 内核中 DEVICE_ATTR 宏构建的设备属性交互机制

通过宏定义的设备属性为 Linux 内核驱动与用户空间的交互提供了一种高效、灵活且安全的方式。以 IPOIB 驱动中的mode属性为例,从属性的定义、参数设置、回调函数的实现,到在实际应用场景中的模式切换操作,以及与其他内核机制的紧密关联,都展示了其在构建强大、可定制的设备驱动系统中的核心地位。深入理解和熟练运用这种设备属性交互机制,对于开发高性能、稳定可靠的 Linux 设备驱动具有重要意义,也为进一步优化系统性能和功能拓展奠定了坚实的基础。

数字人生 449

Linux---驱动属性文件添加、DEVICE_ATTR宏、device_create_file()及sysfs_create_group()

#include <linux/module.h> #include <linux/fs.h> #include <linux/errno.h> #include <linux/miscdevice.h> #include <linux/kernel.h> #include <linux/major.h> #include <linux/mutex.h> #include <linux/proc_fs.h> #i

lihuan680680的博客 7970

CIC-IDS2017数据集训练和测试

1、数据集预处理 1.1整合数据并剔除脏数据 如上图所示,整个数据集是分开的,想要训练,必须要整合在一起,同时在数据集中存在Nan和Infiniti脏数据(只有第15列和第16列存在)需要剔除: 具体代码如下: ```python importpandasaspd #按行合并多个Dataframe数据 defmergeData(): monday=writeData("data\MachineLearningCVE\Monday-W...

蓝亚之舟的博客 2万+

MPN – 制造商物料编号(延伸)

此外,用户还可以在物料主数据中定义阻止MPN材料的原因,以及在采购订单创建时,是否可以将现有的MPN材料修改为其他MPN材料,从而实现对MPN材料的精细控制和管理。通过使用AMPL,用户可以指定每个MPN材料是否仅能为特定工厂或整个企业所有工厂采购、采购的时间段、是否必须属于特定修订级别、是否只能从特定制造商工厂采购以及是否被阻止及其原因。通过AMPL管理,企业可以规范采购流程,避免使用未经批准的材料,从而提高采购的透明度和效率,同时也为质量控制提供了保障‌。3、QM中的制造商物料。质量信息记录QI01。

yanzibing99的博客 2484

DEVICE_ATTR 详解

【官方文档】     官方描述文档路径为 /linux-4.3/Documentation/driver-model/device.txt     源码路径为 /linux-4.3/include/linux/device.h 【DEVICE_ATTR 说明】     原文描述:     ˉˉˉˉˉˉˉˉˉˉˉˉˉ     Attributes are declared usi

一程山水一程歌 7042

【算法】图解A* 搜索算法

A* 算法是启发式搜索算法,是根据Dijkstra算法改进而来。 问题引入 如下图所示,S为起始(start)节点,G为目标(goal)节点。 节点之间连线是两点的路径长度,如A到E的路径长度c(A,E) = 9。 节点旁的h值时当前节点到达目标节点(G)的预估值,如h(A)=15, 表示从当前点A到达目标点G的估计路径长度为15,此处h(x)即为启发函数,启发函数的设计有很多方法,具体可......

zhuhua造轮子的博客 4万+

linux device attr,DEVICE_ATTR的使用

DEVICE_ATTR的使用使用DEVICE_ATTR,可以在sys fs中添加“文件”,通过修改该文件内容,可以实现在运行过程中动态控制device的目的。类似的还有DRIVER_ATTR,BUS_ATTR,CLASS_ATTR。这几个东东的区别就是,DEVICE_ATTR对应的文件在/sys/devices/目录中对应的device下面。而其他几个分别在driver,bus,class中对应的...

weixin_33600827的博客 830

滤波算法-呼吸心跳信号检测方法(四)

呼吸心跳信号检测系列文章:信号滤波处理

yjh_2019的博客 6268

Go语言爬虫:chromedp 的详细使用

chromedp 是 Go 语言中无头浏览器自动化的终极利器。它能驱动真实的 Chrome 浏览器,处理 JavaScript 渲染、复杂交互和反爬虫机制

数据知道的博客 4492

DEVICE_ATTR,device_create_file的使用

使用DEVICE_ATTR,可以在sys fs中添加“文件”,通过修改该文件内容,可以实现在运行过程中动态控制device的目的。 类似的还有DRIVER_ATTR,BUS_ATTR,CLASS_ATTR。 这几个东东的区别就是,DEVICE_ATTR对应的文件在/sys/devices/目录中对应的device下面。 而其他几个分别在driver,bus,class中对应的目录下。

Allen.Yao的专栏 1万+

【数据分析】R语言分段结构方程模型手把手教程(Piecewise Structural Equation Model)

分段结构方程模型(Piecewise Structural Equation Model, SEM)是一种用于分析变量之间因果关系的统计方法。它通过将复杂的因果关系分解为多个简单的线性模型来评估变量之间的直接和间接效应。与传统的结构方程模型(SEM)不同,分段结构方程模型不需要假设数据的多变量正态分布,因此在处理非正态数据时更为灵活。

专注生信领域 2646

使用DEVICE_ATTR添加device节点

DEVICE_ATTR的功能就是定义一个device_attribute结构体对象。 device_create_file利用创建好的device_attribute 在device下创建节点

m0_45064919的博客 1611

课设:FPGA音频均衡器 verilog设计及仿真 加报告

未来,随着FPGA技术的进一步发展和应用场景的扩大,FPGA音频均衡器将发挥出更大的作用,并为音频领域带来更多创新和突破。(a)音乐制作:均衡器可以调整音频信号中不同频段的能量分布,使得乐器声音更加明亮、动感,从而提升音乐制作的质量和创作的灵活性。以上步骤提供了设计一个音频均衡器的大致过程,但值得注意的是,具体实现的细节和复杂度可能因设计要求和所使用的平台而有所不同。确保设计满足预期的性能和要求。确定均衡器的功能和要求:定义你的音频均衡器需要实现的功能,包括频率范围、增益范围以及可调参数数量等。

QQ_778132974的博客 1586

YOLOv8改进策略【卷积层】| CVPR-2023 部分卷积 PConv 轻量化卷积,降低内存占用

本文记录的是利用优化的目标检测方法研究。深度可分离卷积可以减少FLOPs,但会导致更高的内存访问,引起延迟并减慢整体计算。部分卷积利用逐点卷积处理通道冗余,减少模型计算量和内存访问量。Run, Don’t Walk: Chasing Higher FLOPS for Faster Neural Networks及其改进的实现代码如下: 四、创新模块 4.1 改进点⭐ 模块改进方法:直接加入(第五节讲解添加步骤)。模块加入如下:模块改进方法:基于的(第五节讲解添加步骤)。第二种改进方法是对中的进行改进,并将

Limiiiing的博客 1014

DEVICE_ATTR的使用

DEVICE_ATTR的使用 使用DEVICE_ATTR,可以在sys fs中添加“文件”,通过修改该文件内容,可以实现在运行过程中动态控制device的目的。 类似的还有DRIVER_ATTR,BUS_ATTR,CLASS_ATTR。 这几个东东的区别就是,DEVICE_ATTR对应的文件在/sys/devices/目录中对应的device下面。 而其他几个分别在driver,bus

zhubin0613的专栏 580

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

DRIVER_ATTR and DEVICE_ATTR

Driver Attributes ~~~~~~~~~~~~~~~~~ struct driver_attribute {         struct attribute        attr;         ssize_t (*show)(struct device_driver *driver, char *buf);         ssize_t (*store)(stru

咕唧咕唧shubo.lk的专栏 5369

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

linux使用DEVICE_ATTR创建设备节点(常用)

DEVICE_ATTR是一个宏,其定义在include/linux/device.h文件: #define DEVICE_ATTR(_name, _mode, _show, _store) \ struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store) __ATTR宏定义在include/linux...

Android/Linux驱动开发传帮带学习,让驱动入门门槛更低! 1万+

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

linux device_attr 权限,Linux内核宏DEVICE_ATTR使用

1、前言在Linux驱动程序编写中,使用DEVICE_ATTR宏,可以定义一个struct device_attribute设备属性,并使用sysfs的API函数,便可以在设备目录下创建出属性文件,当我们在驱动程序中实现了show和store函数后,便可以使用cat和echo命令对创建出来的设备属性文件进行读写,从而达到控制设备的功能。2、宏DEVICE_ATTR定义在讲解DEVICE_ATTR宏...

weixin_31958413的博客 1138
上一篇: Linux initrd.img的加载机制
下一篇: 内核request_mem_region 和 ioremap的理解
计算机与认知
博客等级 码龄14年 31粉丝 19原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值