zoukankan      html  css  js  c++  java
  • sysfs是什么??

    来源:https://blog.csdn.net/qq_36412526/article/details/83751520

    第一次接触:sysfs, 这里记录过程:

    原文:Documenttation/filesystems/sysfs.txt sysfs-用于导出内核对象(kobject)的文件系统

    sysfs是什么: sysfs是一个基于ram的内存文件系统(ramfs)。它提供了一种方法用于导出内核数据结构,属性,以及它们两者之间的联系到用户空间。 sysfs和kobject结构关联。参考Documenttation/kobject.txt获取更多kobject信息。

    sysfs用法: 如果定义了CONFIG_SYSFS sysfs就会编译进内核。可以用以下命令挂载: mount -t sysfs sysfs /sys

    目录创建 每个注册在系统的kobject都会在sysfs创建一个目录。创建的目录位于kobject的parent目录下,展现了kobject之间的内部层级关系。sysfs顶层的目录表示共同的祖先目录;比如object归属的subsystems。 sysfs内部保存了一个指向kobject的指针。过去kobject指针被sysfs直接用来处理引用次数在文件打开或关闭的时候。现在的sysfs实现了kobject的引用次数只能被函数sysfs_schedule_callback()修改。

    属性(attribute) attribute能为kobject导出普通文件的格式。sysfs用文件I/O操作来操作attribute定义的函数,提供了一种读写内核属性的途径。 attributes应该是ASCII文本文件,最好每个文件保存一个值。有人注意到一个文件保存一个值显得效率不高,所以保存同类型的一组值也是普遍认可的。 混合类型、保存多行数据,且比较花哨的数据是不赞成的。这样做会让你在公众面前丢脸且你的代码会被毫无征兆地重写。 attribute定义如下

    struct attribute{
    	char *name;
    	struct module *owner;
    	mode_t mode;
    	};
    
    int sysfs_create_file(struct kobject *kobj,const struct attribute *attr);
    void sysfs_remove_file(struct kobject *kobj,const struct attribute *attr);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    空的attribute不含读写attribute的函数。子系统(subsystems)鼓励定义自己的attribute结构体和包装函数用于添加和删除object的attribute。

    举例来说,设备驱动模型定义了device_attribute的结构体如下:

    struct device_attribute{
    	struct attribute attr;
    	ssize_t (*show)(struct device *dev,struct device_attribute *attr,char *buf);
    	ssize_t (*strore)(struct device *dev,struct device_attibute *attr,char *buf,size_t count);
    	};
    int device_create_file(struct device *,const struct device_attribute *);
    void device_remove_file(struct device *,const struct device_attribute *);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    它同时定义了辅助宏来定义设备attributes:

    #define DEVICE_ATTR(_name,_mode,_show,_store)
    struct device_attribute dev_attr_##_name =__ATTR(_name,_mode,_show,_store)
    
    • 1
    • 2

    举例,声明

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

    等效于:

    static struct device_attribute dev_attr_foo = 
    	.attr = {
    	.name = "foo",
    	.mode = S_IWUSR | S_IRUGO,
    	.show = show_foo,
    	.store = store_foo,
    	},
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    subsystem相关的callbacks

    当subsystem定义了新的attribute类型,它必须实现一组自己的sysfs操作函数用于sysfs读写调用.

    struct sysfs_ops {
            ssize_t (*show)(struct kobject *, struct attribute *, char *);
            ssize_t (*store)(struct kobject *, struct attribute *, const char *, size_t);
    };
    
    • 1
    • 2
    • 3
    • 4

    [subsystems 应该已经定义了一个kobj_type结构体作为类型描述符,它保存了sysfs_ops指针.详情参考kobject文档.]

    当读写文件的时候,sysfs调用kobj_type的相应方法函数.该函数随后转换kobject和attribute指针到相应的指针类型,然后调用相应的方法函数. 举例:

    #define to_dev(obj) container_of(obj, struct device, kobj)
    #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr)
    
    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 = -EIO;
    
            if (dev_attr->show)
                    ret = dev_attr->show(dev, dev_attr, buf);
            if (ret >= (ssize_t)PAGE_SIZE) {
                    print_symbol("dev_attr_show: %s returned bad count
    ",
                                    (unsigned long)dev_attr->show);
            }
            return ret;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    读/写 attribute 数据 为了读写attribute,在声明attribute的时候必须定义show()或store()函数.这些函数应该尽量简单如device attribute定义的函数:

    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);
    
    • 1
    • 2
    • 3

    IOW,这些函数只需要一个object,attribute,buffer作为参数. sysfs分配了一个buffer(PAGE_SIZE字节)并把它传入这些函数.sysfs会在每次读写的时候调用这些函数.要求这些函数实现以下功能:

    -on read(2),show()函数会填充整个buffer.一个attribute应该只导出一个值,或一组相似的值,因此这个效率不高. 这 使用户空间可以部分读且随意向后搜索.如果用户空间向前搜索到0或使用pread(2)在0位置读,show()函数会被再次调用        并填充整个buffer.

    -on write(2),sysfs在首次写的时候传递整个buffer,sysfs然后传递整个buffer到store()函数. 当写sysfs文件时,用户空间先读整个文件,然后修改,最后再写回文件. attribute函数读和写的时候应该使用同一个buffer.

    其他注意点:

    -写操作将导致show()函数被再次调用,不管当前文件位置在哪里.

    -buffer的长度固定为PAGE_SIZE.在i386,长度为4096

    -show()函数返回输出到buffer的字节数.也就是scnprintf()函数的返回值

    -show()函数应该使用scnprintf()函数

    -store()函数应该返回buffer占用的字节数,如果整个buffer都被占用,应该返回count参数

    -show()和store()函数可以返回错误,如果有错误的值,确保返回一个错误

    -函数的参数object将被保存在内存中通过它的引用计数器计数.但object代表的实体不一定在内存中,如果有必要,要有方法检测.

    一个设备属性的简单的实现如下:

    static ssize_t show_name(struct device *dev, struct device_attribute *attr,
                             char *buf)
    {
    	return scnprintf(buf, PAGE_SIZE, "%s
    ", dev->name);
    }
    
    static ssize_t store_name(struct device *dev, struct device_attribute *attr,
                              const char *buf, size_t count)
    {
            snprintf(dev->name, sizeof(dev->name), "%.*s",
                     (int)min(count, sizeof(dev->name) - 1), buf);
    	return count;
    }
    
    static DEVICE_ATTR(name, S_IRUGO, show_name, store_name);
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    (注意,实际上设备的名字不能在用户空间更改.)

    顶层目录安排

    sysfs目录展现了内核数据结构之间的关系. 顶层目录如下: block/ bus/ class/ dev/ devices/ firmware/ net/ fs/

    devices/ 一个文件系统代表了设备树(device tree).直接映射到内核的设备树,它是device结构体的层级关系. bus/ 内核的多种总线类型的目录布局.每个总线目录含两个子目录: devices/ 系统里发现的每个设备的符号连接指向root/目录下的 device目录 drivers/ 特定总线上设备加载的驱动目录 fs/  某些文件系统的目录.每个文件系统如果要导出attributes必须要创建它自己的目录层级到fs/下 dev/ 里面有两个目录char/和block/.这两个目录里有命名为:的符号连接.这些符号连接到sysfs目录下对应的device./sys/dev提供了一个快速的方式来查找sysfs中stat操作的结果

    更多关于驱动模型的特征信息可以参考Documentation/driver-model/.

    Current Interfaces

    The following interface layers currently exist in sysfs:

    • devices (include/linux/device.h)

    Structure:

    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);
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    Declaring:

    DEVICE_ATTR(_name, _mode, _show, _store);
    
    • 1

    Creation/Removal:

    int device_create_file(struct device *dev, const struct device_attribute * attr);
    void device_remove_file(struct device *dev, const struct device_attribute * attr);
    
    
    • 1
    • 2
    • 3
    • bus drivers (include/linux/device.h)

    Structure:

    struct bus_attribute {
            struct attribute        attr;
            ssize_t (*show)(struct bus_type *, char * buf);
            ssize_t (*store)(struct bus_type *, const char * buf, size_t count);
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5

    Declaring:

    BUS_ATTR(_name, _mode, _show, _store)
    
    • 1

    Creation/Removal:

    int bus_create_file(struct bus_type *, struct bus_attribute *);
    void bus_remove_file(struct bus_type *, struct bus_attribute *);
    
    
    • 1
    • 2
    • 3
    • device drivers (include/linux/device.h)

    Structure:

    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);
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    Declaring:

    DRIVER_ATTR(_name, _mode, _show, _store)
    
    
    • 1
    • 2

    Creation/Removal:

    int driver_create_file(struct device_driver *, const struct driver_attribute *);
    void driver_remove_file(struct device_driver *, const struct driver_attribute *);
    
    
    • 1
    • 2
    • 3

    文档

    sysfs目录结构和每个目录的attribute定义了一种ABI在内核和用户空间.对于任何ABI,稳定和正确的文档是很重要的.所有新的sysfs attributes必须配上文档.参考Documentation/ABI/README阅读更多的信息.

  • 相关阅读:
    优化Hibernate所鼓励的7大措施:
    Java未赋值变量的默认初始值
    年轻代
    JVM介绍
    Java锁的种类以及辨析
    java语言复制数组的四种方法
    static和final
    抽象函数抽象类
    try catch finally
    九大内置对象
  • 原文地址:https://www.cnblogs.com/MCSFX/p/10886760.html
Copyright © 2011-2022 走看看