公众号【嵌入式er笔记】持续记录和分享C/C++、Linux、ARM、Android、IoT等技术相关知识,以及职场、生活经验和感悟。
分类: LINUX
2015-03-09 23:11:06
sysfs
是 Linux 内核中设计较新的一种虚拟的基于内存的文件系统,它的作用与 proc 有些类似,但除了与 proc
册虚拟的字符设备文件,以这个虚拟设备上的 read/write/ioctl 等接口与用户交互;但 read/write 一般只能做一件事情, ioctl 可以根据 cmd 参数做多个功能,但其缺点是很明显的: ioctl 接口无法直接在 Shell 脚本中使用,为了使用 ioctl 的功能,还必须编写配套的 C语言的虚拟设备操作程序, ioctl 的二进制数据接口也是造成大小端问题 (big endian与little endian)、32位/64位不可移植问题的根源; 最 重要的是,添加虚拟字符设备支持和注册 proc 接口支持这两者所需要增加的代码量都并不少,最好的方法还是使用 sysfs 属性支持,一切在用户层是可见的透明,且增加的代码量是最少的,可维护性也最好;方法就是使用 头文件提供的这四个宏,分别应用于总线/类别/驱动/设备四种内核数据结构对象上: #define BUS_ATTR(_name, _mode, _show, _store) \ struct bus_attribute bus_attr_##_name = __ATTR(_name, _mode, _show, _store) #define CLASS_ATTR(_name, _mode, _show, _store) \ struct class_attribute class_attr_##_name = __ATTR(_name, _mode, _show, _store) #define DRIVER_ATTR(_name, _mode, _show, _store) \ struct driver_attribute driver_attr_##_name = \ __ATTR(_name, _mode, _show, _store) #define DEVICE_ATTR(_name, _mode, _show, _store) \ struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store) 总线(BUS)和类别(CLASS)属性一般用于新设 计的总线和新设计的类别,这两者一般是不用的;因为你的设备一般是以PCI等成熟的常规方式连接到主机,而不会去新发明一种类型;使用驱动属性和设备属性 的区别就在于:看你的 sysfs 属性设计是针对整个驱动有效的还是针对这份驱动所可能支持的每个设备分别有效。 从头文 件中还可以找到 show/store 函数的原型,注意到它和虚拟字符设备或 proc 项的 read/write 的作用很类似,但有一点不同是 show/store 函数上的 buf/count 参数是在 sysfs 层已作了用户区/内核区的内存复制,虚拟字符设备上常见的 __user 属性在这里并不需要,因而也不需要多一次 copy_from_user/copy_to_user, 在 show/store 函数参数上的 buf/count 参数已经是内核区的地址,可以直接操作。 上面四种都是 Linux 统一设备模型所添加的高级接口,如果使用 sysfs 所提供的底层接口的话,则还有下面两个,定义来自 :(上面的总线/类别/驱动/设备四个接口都是以这里的__ATTR实现的) #define __ATTR(_name,_mode,_show,_store) { \ .attr = {.name = __stringify(_name), .mode = _mode }, \ .show = _show, \ .store = _store, \ } #define __ATTR_RO(_name) { \ .attr = { .name = __stringify(_name), .mode = 0444 }, \ .show = _name##_show, \ } 上 面这些宏都是在注册总线/类别/驱动/设备时作为缺省属性而使用的,在实际应用中还有一种情况是根据条件动态添加属性,如 PCI 设备上的 resource{0,1,2,...} 属性文件,因为一个 PCI 设备上的可映射资源究竟有多少无法预知,也只能以条件判断的方式动态添加上。 int __must_check sysfs_create_file(struct kobject *kobj, const struct attribute *attr); int __must_check sysfs_create_bin_file(struct kobject *kobj, struct bin_attribute *attr); 这两个函数可以对一个 kobject 动态添加上文本属性或二进制属性,这也是唯一可以添加二进制属性的方法。 二进制属性与普通文本属性的区别在于:
编程示例,对 LDD3 一书中的 lddbus 驱动程序的 sysfs 改进 首先,这个程序本身是针对当时作者写书的年代的内核(2.6.11)而编写的,在当前的 Fedora10 系统 (2.6.27.5-117.fc10.i686) 上甚至无法编译编译通过;因此首先需要将它移植过来至少达到可运行状态; 附件的压缩包中含有修改过的 lddbus, sculld 的源代码和修改过程的四个patch:
回页首 小结 sysfs 给应用程序提供了统一访问设备的接口,但可以看到, sysfs 仅仅是提供了一个可以统一访问设备的框架,但究竟是否支持 sysfs 还需要各设备驱动程序的编程支持;在 2.6 内核诞生 5年以来的发展中,很多子系统、设备驱动程序逐渐转向了 sysfs 作为与用户空间友好的接口,但仍然也存在大量的代码还在使用旧的 proc 或虚拟字符设备的 ioctl 方式;如果仅从最终用户的角度来说, sysfs 与 proc 都是在提供相同或类似的功能,对于旧的 proc 代码,没有绝对的必要去做 proc 至 sysfs 的升级;因此在可预见的将来, sysfs 会与 proc, debugfs, configfs 等共存很长一段时间。 转自:http://www.ibm.com/developerworks/cn/linux/l-cn-sysfs/ |