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. hdu5141 线段树

    这题说的是给了一串然后计算出这个串的最长递增子序列的长度,然后计算出有过少个子串[i,j] 他们的最长递增子序列和这整个子串的最长递增子序列相同,我们对于每个j最长递增子序列找出他在序列中的使成为最长 ...

  2. 在使用swiper时,解决同一个页面使用多个轮播出现问题做法

    $(".swiper-container").each(function(){ $(this).swiper({ loop: true, initialSlide :0, pagi ...

  3. Python3.x:os.chdir(改变当前路径方法)介绍

    Python3.x:os.chdir(改变当前路径方法)介绍 1,os.chdir() import os os.chdir(r'C:\python36\test_chdir') 说明:chdir() ...

  4. 20145219《网络对抗》Web基础

    20145219<网络对抗>Web基础 基础问题回答 什么是表单? HTML表单用于收集用户输入,用<form>元素定义,包含不同类型的 input元素.复选框.单选按钮.提交 ...

  5. 2017-2018-1 JaWorld 团队作业--冲刺1

    2017-2018-1 JaWorld 团队作业--冲刺1(20162301) 一.小组分工: 由于小组成员在本周比较忙碌,所以考虑后本组的冲刺就按照每天加入不同的类来完成.我们根据类的难度大小来决定 ...

  6. Python学习笔记:与Java 基础语法对比

    闲着无聊学习下Python 的语法.由于我目前主要编程语言还是Java ,所以针对Python 的学习我主要是通过与Java 进行对比.我使用的是Python3,因此语法上也会遵循Python3 的规 ...

  7. Java加密代码 转换成Net版

    java版本自己封装base64 package com.qhong; import java.io.UnsupportedEncodingException; import org.apache.c ...

  8. display:box,按比列划分,水平均分,及垂直等高

    一.按比例划分 <div class="test"> <p id="p1">Hello</p> <p id=" ...

  9. 使用属性动画 — Property Animation

    属性动画,就是通过控制对象中的属性值产生的动画.属性动画是目前最高级的2D动画系统. 在API Level 11中添加.Property Animation号称能控制一切对象的动画,包括可见的和不可见 ...

  10. [osgearth]oe学习的一些经验(别人的)

    参考:http://bbs.osgchina.org/forum.php?mod=viewthread&tid=5484&extra=page%3D1&_dsign=70b15 ...