Documentation/filesystems/sysfs.txt 文档翻译--sysfs
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的更多相关文章
- Linux内核文档翻译——sysfs.txt
sysfs - _The_ filesystem for exporting kernel objects. sysfs – 用于导出内核对象(kobject)的文件系统 Patrick Mochel ...
- Documentation/PCI/pci-iov-howto.txt
Chinese translated version of Documentation/PCI/pci-iov-howto.txt If you have any comment or update ...
- Documentation/usb/gadget_configfs.txt
Linux USB gadget configured through configfs 25th April 2013 Overview======== A USB Linux Gadget is ...
- sysfs文件系统学习--sysfs
一.sysfs简介1.sysfs就是利用VFS的接口去读写kobject的层次结构,建立起来的文件系统.其更新与删除是那些xxx_register()/unregister()做的事 情.从sysfs ...
- Documentation/kobject.txt翻译--sysfs
你从未想过的关于kobjects,ksets和ktypes的一切:作者:Greg Kroah-Hartman <gregkh@linuxfoundation.org>:上次更新时间:200 ...
- (转)Linux 文件系统:procfs, sysfs, debugfs 用法简介
网址:http://www.tinylab.org/show-the-usage-of-procfs-sysfs-debugfs/ 1 前言 内核中有三个常用的伪文件系统:procfs,debugfs ...
- 内核交互--sysfs
文档介绍:http://lxr.linux.no/linux+v2.6.37/Documentation/filesystems/sysfs.txt The sysfs Filesystem Sysf ...
- Linux内核文档翻译之Squashfs文件系统
转载:http://blog.csdn.net/gqb_driver/article/details/12946629 对于使用openwrt的嵌入式系统来说,因为硬件绝大多数采用Flash,因此一般 ...
- Where is the kernel documentation?; Ubuntu 上如何安装 linux 内核文档;fedora 上如何安装linux内核文档?
有时候,linux内核文档对我们很重要,我们可以在linux系统中安装,并及时查看: 参考链接:https://askubuntu.com/questions/841043/where-is-the- ...
随机推荐
- 理解Linux系统中的load average(图文版)
本文转自:http://heipark.iteye.com/blog/1340384 一.什么是load average? linux系统中的Load对当前CPU工作量的度量 (WikiPedia: ...
- pyDay12
内容来自廖雪峰的官方网站. 1.可迭代对象(Iterable):可以直接作用于for循环的对象. 2.集合数据类型:如list.tuple.dict.set.str等. 3.generator:包括生 ...
- Python面试题目之字典排序
按照字典的内的年龄排序 待排序的字典 d1 = [ {'name':'alice', 'age':38}, {'name':'bob', 'age':18}, {'name':'Carl', 'age ...
- bzoj1297 / P4159 [SCOI2009]迷路
P4159 [SCOI2009]迷路 如果边权只有 0/1 那么不就是一个灰常简单的矩阵快速幂吗! 然鹅边权 $<=9$ 所以我们把每个点拆成9个点! 解决~ #include<iostr ...
- 20145326 《Java程序设计》第9周学习总结
20145326 <Java程序设计>第9周学习总结 教材学习内容总结 第十六章 一.JDBC入门 1.JDBC简介 JDBC是用于执行SQL的解决方案,开发人员使用JDBC的标准接口,数 ...
- 全局变量的使用【C++/Qt】
转:https://blog.csdn.net/caoshangpa/article/details/51104022 一.使用extern关键字 cglobal.h #ifndef CGLOBAL_ ...
- python 读取位于包中的数据文件
假设你的包中的文件组织成如下: mypackage/ __init__.py somedata.dat spam.py 现在假设spam.py文件需要读取somedata.dat文件中的内容.你可以用 ...
- 数据结构与算法(python版)教程
算法的性质 算法的描述 算法的设计与分析
- UriComponentsBuilder和UriComponents url编码
Spring MVC 提供了一种机制,可以构造和编码URI -- 使用UriComponentsBuilder和UriComponents. 功能相当于 urlencode()函数,对url进行编码, ...
- bzoj2330: [SCOI2011]糖果 差分约束系统
幼儿园里有N个小朋友,lxhgww老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果.但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配糖果的时候 ...