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. 121. Best Time to Buy and Sell Stock(股票最大收益)

    Say you have an array for which the ith element is the price of a given stock on day i. If you were ...

  2. 20145322 何志威《网络对抗》shellcode注入&Return-to-libc攻击深入

    基础知识 Shellcode实际是一段代码,但却作为数据发送给受攻击服务器,将代码存储到对方的堆栈中,并将堆栈的返回地址利用缓冲区溢出,覆盖成为指向 shellcode的地址. execstack - ...

  3. linux及安全《Linux内核设计与实现》第四章——20135227黄晓妍

    第四章 进程调度 进程调度程序是一个内核子系统 分配有限的处理器时间和资源 最大限度利用时间的原则(只要有可执行的进程,那么总会有进程执行) 基本工作:从一组处于等待(阻塞)状态的可执行进程中选择一个 ...

  4. Dijkstra算法补分

    要求 Dijkstra算法,求解附图顶点A的单源最短路径 在纸上画出求解过程,上传截图(注意图上要有自己的学号和姓名) 过程

  5. 使用ShellExecute打开目标文件所在文件夹并选中目标文件

    转载:http://blog.csdn.net/chenlycly/article/details/7366364 转载:http://bbs.csdn.net/topics/50440550 She ...

  6. UVa 11021 麻球繁衍

    https://vjudge.net/problem/UVA-11021 题意:有k只麻球,每只活一天就会死亡,临死之前可能会生出一些新的麻球.具体来说,生i个麻球的概率为Pi.给定m,求m天后所有麻 ...

  7. UVa 11732 strcmp()函数(左孩子右兄弟表示法)

    #include<iostream> #include<algorithm> #include<string> #include<cstring> #i ...

  8. 关于keyCode, 键盘代码。 和零散的javascript知识。http://js2.coffee/(转化工具)

    这个是coffeescript代码 document.addEventListener 'turbolinks:load', ->   document.getElementById(" ...

  9. Tornado源码分析 --- Etag实现

    Etag(URL的Entity Tag): 对于具体Etag是什么,请求流程,实现原理,这里不进行介绍,可以参考下面链接: http://www.oschina.net/question/234345 ...

  10. windows下的IO模型之异步选择(WSAAsyncSelect)模型

    异步选择(WSAAsyncSelect)模型是一个有用的异步I/O 模型.其核心函数是WSAAsyncSelect,该函数是非阻塞的 (关于异步io的理解详情可以看:http://www.cnblog ...