sysfs - 用于导出内核对象的文件系统。

1.sysfs是一个基于ram的文件系统,最初基于ramfs。 它提供了一种方法,可以将内核数据结构,它们的属性以及它们之间的链接导出到用户空间。
sysfs本质上与kobject基础结构相关联。有关kobject接口的更多信息,请阅读Documentation/kobject.txt

2.使用sysfs
如果定义了CONFIG_SYSFS,则始终编译sysfs。 你可以通过这样做进行访问:mount -t sysfs sysfs /sys

3.sysfs中目录的创建
对于在系统中注册的每个kobject,都会在sysfs中为其创建一个目录。 该目录创建为kobject父项的子目录,表示内部对象层次结构到用户
空间。 sysfs中的顶级目录代表对象层次结构的共同祖先; 即对象所属的子系统。
Sysfs在内部存储指向kobject的指针,该kobject实现与该目录关联的kernfs_node对象中的目录。 在过去,只要文件被打开或关闭,sysfs
就会使用这个kobject指针直接在kobject上进行引用计数。 使用当前的sysfs实现,kobject引用计数仅由函数sysfs_schedule_callback()
直接修改。

4.属性
可以在文件系统中以常规文件的形式为kobjects导出属性。 Sysfs将文件I/O操作转换为属性定义的方法,从而提供读取和写入内核属性的方法。
属性应该是ASCII文本文件,最好每个文件只有一个值。 注意,每个文件仅包含一个值可能效率不高,因此表达相同类型数组也是可接受的。
混合类型,表达多行数据以及进行数据格式化是非常不受欢迎的。 做这些事情可能会让你公开羞辱,你的代码会被重写,恕不另行通知。

属性定义很简单:

struct attribute {
char * name;
struct module *owner;
umode_t mode;
};
int sysfs_create_file(struct kobject * kobj, const struct attribute * attr);
void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr);

bare属性不包含读取或写入属性值的方法。 鼓励子系统定义自己的属性结构和包装函数,以便为特定对象类型添加和删除属性。

例如,驱动程序模型定义struct 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 *, const struct device_attribute *);
void device_remove_file(struct device *, const struct device_attribute *);

它还定义了这个帮助函数来定义设备属性:

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

例如,声明:

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

5.子系统特定的回调
当子系统定义新的属性类型时,它必须实现一组sysfs操作,以便将读取和写入调用转发到属性所有者的show()和store()方法。

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

[子系统应该已经为此类型定义了一个struct kobj_type描述符,这是存储sysfs_ops指针的位置。 有关更多信息,请参阅kobject文档。]

读取或写入文件时,sysfs会调用该类型的相应方法。 然后,该方法将通用struct kobject和struct 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\n", (unsigned long)dev_attr->show);
}
return ret;
}

6.读/写属性数据
要读取或写入属性,必须在声明属性时指定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, size_t count);

IOW,他们应该只将一个object,一个attribute和一个buffer 作为参数。

sysfs分配一个大小为(PAGE_SIZE)的缓冲区并将其传递给该方法。 Sysfs将为每次读取或写入调用该方法一次。 这会在方法实现上强制执
行以下行为:

- 在read(2)中,show()方法应该填满整个缓冲区。 回想一下,一个属性应该只导出一个值,或者一个类似值的数组,所以应该不会有那
么大的开销。
这允许用户空间随意对整个文件进行部分读取和forward seeks。 如果用户空间seeks back到0或者使用偏移量为“0”的pread(2),将再次
调用show()方法,重新启动以填充缓冲区。

- 在write(2)时,sysfs期望在第一次写入期间传递整个缓冲区。 然后,Sysfs将整个缓冲区传递给store()方法。 在数据传到store()之后
应添加终止NULL。 这使得sysfs_streq()等函数可以安全使用。
在写sysfs文件时,用户空间进程应首先读取整个文件,修改它希望更改的值,然后再写回整个缓冲区。
在读取和写入值时,属性方法实现应在相同的缓冲区上运行。

7.其他说明:
- 无论当前文件位置如何,写入都会使show()方法重置。这个普通的文件偏移方法不同!!
- 缓冲区的长度始终为PAGE_SIZE个字节。 在i386上,这是4096。
- show()方法应该返回打印到缓冲区中的字节数。 这是scnprintf()的返回值。
- 格式化要返回给用户空间的值时,show()不得使用snprintf()。 如果你能保证永远不会发生溢出,你可以使用sprintf(),否则你必须使用scnprintf()。
- store()应返回缓冲区使用的字节数。 如果已使用整个缓冲区,则只返回count参数。
- show()或store()总是可以返回错误。 如果出现错误值,请务必返回错误。

- 传递给方法的object将通过引用计数其嵌入对象的sysfs固定在内存中。但是,对象所代表的物理实体(例如设备)可能不存在。 如有必要,请务必检查此方法。

8.设备属性的一个非常简单(和天真)的实现是:

static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf)
{
return scnprintf(buf, PAGE_SIZE, "%s\n", 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);

(请注意,实际实现不允许用户空间设置设备的名称。)

9.上层目录结构
sysfs目录暴露了内核数据结构的关系。顶级sysfs目录如下所示:
block/ bus/ class/ dev/ devices/ firmware/ net/ fs/

devices/ 包含设备树的文件系统表示。它直接映射到内部内核设备树,这是struct device的层次结构。
bus/ 包含内核中各种总线类型的目录布局。每个总线的目录包含两个子目录:
       devices/
       drivers/
devices/ 包含系统中发现的每个设备的符号链接,指向root/ 下的设备目录。
drivers/ 包含为该特定总线上的设备加载的每个设备驱动程序的目录(假设驱动程序不跨越多种总线类型)。
fs/ 包含某些文件系统的目录。目前,每个想要导出属性的文件系统必须在fs/ 下创建自己的层次结构(例如,参见./fuse.txt)。
dev/ 包含两个目录char/ 和block/。在这两个目录中有一些名为<major>:<minor>的符号链接。这些符号链接指向给定设备的sysfs目录。 /sys/dev 提供了一种从stat(2)操作的结果中查找设备的sysfs接口的快速方法。

更多信息可以在Documentation/driver-model/中找到驱动程序模型特定功能。

10.目前的接口
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);
};
声明:
DEVICE_ATTR(_name, _mode, _show, _store);
创建/移除:
int device_create_file(struct device *dev, const struct device_attribute * attr);
void device_remove_file(struct device *dev, const struct device_attribute * attr); - 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);
};
声明:
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)
-----------------------------------------
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);
};
声明:
DRIVER_ATTR_RO(_name)
DRIVER_ATTR_RW(_name)
创建/移除:
int driver_create_file(struct device_driver *, const struct driver_attribute *);
void driver_remove_file(struct device_driver *, const struct driver_attribute *);

11.文档
sysfs目录结构和每个目录中的属性定义了内核和用户空间之间的ABI。至于任何ABI,重要的是这个ABI是稳定的并且有适当的记录。 必须在
Documentation/ABI中记录所有新的sysfs属性。 有关更多信息,另请参见Documentation/ABI/README

Documentation/filesystems/sysfs.txt 文档翻译--sysfs的更多相关文章

  1. Linux内核文档翻译——sysfs.txt

    sysfs - _The_ filesystem for exporting kernel objects. sysfs – 用于导出内核对象(kobject)的文件系统 Patrick Mochel ...

  2. Documentation/PCI/pci-iov-howto.txt

    Chinese translated version of Documentation/PCI/pci-iov-howto.txt If you have any comment or update ...

  3. Documentation/usb/gadget_configfs.txt

    Linux USB gadget configured through configfs 25th April 2013 Overview======== A USB Linux Gadget is ...

  4. sysfs文件系统学习--sysfs

    一.sysfs简介1.sysfs就是利用VFS的接口去读写kobject的层次结构,建立起来的文件系统.其更新与删除是那些xxx_register()/unregister()做的事 情.从sysfs ...

  5. Documentation/kobject.txt翻译--sysfs

    你从未想过的关于kobjects,ksets和ktypes的一切:作者:Greg Kroah-Hartman <gregkh@linuxfoundation.org>:上次更新时间:200 ...

  6. (转)Linux 文件系统:procfs, sysfs, debugfs 用法简介

    网址:http://www.tinylab.org/show-the-usage-of-procfs-sysfs-debugfs/ 1 前言 内核中有三个常用的伪文件系统:procfs,debugfs ...

  7. 内核交互--sysfs

    文档介绍:http://lxr.linux.no/linux+v2.6.37/Documentation/filesystems/sysfs.txt The sysfs Filesystem Sysf ...

  8. Linux内核文档翻译之Squashfs文件系统

    转载:http://blog.csdn.net/gqb_driver/article/details/12946629 对于使用openwrt的嵌入式系统来说,因为硬件绝大多数采用Flash,因此一般 ...

  9. Where is the kernel documentation?; Ubuntu 上如何安装 linux 内核文档;fedora 上如何安装linux内核文档?

    有时候,linux内核文档对我们很重要,我们可以在linux系统中安装,并及时查看: 参考链接:https://askubuntu.com/questions/841043/where-is-the- ...

随机推荐

  1. AtCoder Grand Contest 029 Solution

    A: Solved. 签. #include <bits/stdc++.h> using namespace std; #define ll long long #define N 200 ...

  2. Uva11374 Dijkstra

    机场快线是市民从市内去机场的首选交通工具.机场快线分为经济线和商业线两种,线路.速度和价格都不同,你有一张商业线车票,可以坐一站商业线,而其他时候,只能乘坐经济线.假设换乘时间忽略不计,你的任务是找一 ...

  3. Python:执行精确的浮点数运算

    需要对浮点数执行精确的计算操作,并且不希望有任何小误差的出现. 浮点数的一个普遍问题是它们并不能精确的表示十进制数.并且,即使是最简单的数学运算也会产生小的误差,比如: >>> a ...

  4. SQLServer cast()函数

    语法: CAST (expression AS data_type) 参数说明: expression:任何有效的SQLServer表达式. AS:用于分隔两个参数,在AS之前的是要处理的数据,在AS ...

  5. PHP文件锁 解决并发问题

    使用多线程或是多进程时. 难免会遇到并发问题. 处理简单的并发可以使用这个办法来解决 flock($fp = fopen($lock, 'w+'), LOCK_EX | LOCK_NB)   or e ...

  6. QT之QML控件篇

    QT quick中提供了很多的实用控件widget,下面介绍几种常用的. 这部分介绍基本是参照QtCretator提供的帮助文档,一定要学会使用,不明白的去查找帮助. Item 基本上所有的可是控件的 ...

  7. 2018-2019-1 20189218《Linux内核原理与分析》第二周作业

    问题一 动态库链接找不到库问题 这个问题当时确实对我造成了很大的困扰,虽然最终仍然成功用动态库链接但是问题并没有解决.现在回过头来看却觉得有点蠢,但出错的过程仍然值得总结.首先看我的目录结构: 可以看 ...

  8. 2017-2018-1 JaWorld 第三周作业

    2017-2018-1 JaWorld 第三周作业 团队展示 队员学号 队名 团队项目描述 队员风采 团队的特色 团队合照 团队初步合作 前两周的反思与总结 需要改进的地方 团队选题 *采访老师或有开 ...

  9. Javaworkers团队第三周项目总结

    第十三.十四周:按照项目设计,逐步完成各个模块的代码,初步完成项目雏形. 基础知识原理 1.TDD(Test Driven Development, 测试驱动开发),TDD的一般步骤如下: 明确当前要 ...

  10. 如何在编辑框中使用IAutoComplete接口(转载)

    出自:http://www.vckbase.com/index.php/wv/27.html 如果可能我想用打包类来实现.唉!,就叫我封装先生吧. 你算是找对地方了.但是我要先声明我的解决办法不是你所 ...