深入概述sysfs文件系统,有这一篇就够了!
内核源码:linux-2.6.38.8.tar.bz2
目标平台:ARM体系结构
sysfs是基于内存的文件系统,用于向用户空间导出内核对象并且能对其进行读写。
1、sysfs文件系统不支持特殊文件,只支持目录、普通文件(文本或二进制文件)和符号链接文件等三种类型,在内核中都使用struct sysfs_dirent结构体来表示,相当于其他文件系统在硬盘或flash里的数据。源代码如下所示:
struct sysfs_dirent分为四种类型,如下所示:
struct sysfs_open_dirent等结构体的详细信息后文说明。
【文章福利】小编推荐自己的Linux内核技术交流群:【891587639】整理了一些个人觉得比较好的学习书籍、视频资料共享在群文件里面,有需要的可以自行添加哦!!!(含视频教程、电子书、实战项目及代码)


2、sysfs文件系统的初始化是由sysfs_init函数来完成的(该函数由vfs_caches_init函数所调用的mnt_init函数调用),执行文件系统的注册和挂载,与rootfs根文件系统的相关操作类似。源代码如下所示:
在用户空间一般都将sysfs文件系统挂载在/sys目录,而这里也有一次通过kern_mount函数的挂载,这样的话 sysfs文件系统就会挂载两次?其实是没有的,后者的挂载并没有将当前的struct vfsmount结构体实例插入到挂载树中,而是保存在全局指针sysfs_mnt中,并且会与用户空间挂载sysfs文件系统时所创建的struct vfsmount结构体实例共享相同的超级块。因此,无论用户空间的挂载操作是否执行,sysfs文件系统都会存在于内核之中(编译内核有配置CONFIG_SYSFS选项)。sysfs文件系统的struct file_system_type结构体实例如下所示:
其中,sysfs_test_super函数用于判断struct sysfs_super_info结构体数据是否相同以便确认是否可以共享超级块,源代码如下所示:
sysfs_fill_super函数主要用于创建sysfs文件系统根目录所对应的目录项及其i节点,并且将sysfs_root作为根目录项的私有数据。源代码如下所示:
3、文件系统最核心的内容是要看其i节点是如何构建的,sysfs文件系统使用sysfs_init_inode函数来创建。源代码如下所示:
四种structsysfs_dirent类型对应三种文件类型,其中SYSFS_KOBJ_ATTR和SYSFS_KOBJ_BIN_ATTR都为普通文件。文件系统针对不同的文件类型,i节点操作函数(struct inode_operations)和文件内容操作函数(struct file_operations)都会有不同的实现,并且其中的函数也是根据文件类型来决定是否实现(大部分成员为空指针)。
3.1、目录的i节点操作函数和文件内容操作函数分别为sysfs_dir_inode_operations和sysfs_dir_operations,其中i节点操作函数的create、mkdir和rmdir等成员都为空指针,表示sysfs文件系统的目录或文件无法从用户空间通过系统调用来创建和删除。对于sysfs文件系统中的目录来说,i节点操作函数最重要的是查找函数sysfs_lookup,文件内容操作函数最重要的是遍历目录函数sysfs_readdir。源代码如下所示:
对于目录来说,只能有一个目录项别名。
当在用户空间通过ls等命令查看sysfs文件系统的目录时,会通过系统调用getdents调用vfs_readdir,然后再调用sysfs_readdir函数。其中参数filp表示该目录打开之后的文件指针,dirent实际为struct getdents_callback类型的数据,filldir为回调函数指针,指向同名的filldir函数。源代码如下所示:
3.2、sysfs文件系统针对文本文件和二进制文件实现了不同的文件内容操作函数,而i节点操作函数则相同。源代码如下所示:
针对普通文件,最重要的是观察它的文件内容操作函数的实现,如open、read和write等函数。下面则以文本文件为例,看看sysfs文件系统是如何读写文件的。源代码如下所示:
在sysfs文件系统中,文本文件使用struct sysfs_elem_attr来表示,而该结构体有一个struct sysfs_open_dirent类型的open成员,主要用于管理每次打开并读/写该文件时所使用的内存(struct sysfs_buffer)。源代码如下所示:
sysfs_read_file为sysfs文件系统文本文件的读函数,源代码如下所示:
sysfs_write_file为sysfs文件系统的写函数,源代码如下所示:
关闭文件时,打开、读/写文件时所分配的内存都会释放,并不会一直存在于内核中。
3.3、对于符号链接文件来说,它没有文件内容操作函数,只有i节点操作函数,其中最重要的函数为符号链接文件的解析函数sysfs_follow_link,源代码如下所示:
读取符号链接文件内容的函数generic_readlink主要就是靠解析函数来实现的,源代码如下所示:
其中,sysfs_put_link函数执行与sysfs_follow_link函数相反的操作,这里只是释放由sysfs_follow_link函数分配的内存。
4、对于sysfs文件系统来说,在用户空间只能读写文件的内容,而无法创建或删除文件或目录,只能在内核中通过sysfs_create_dir、sysfs_create_file等等函数来实现。
4.1、内核对象(struct kobject)对应于sysfs文件系统中的目录,可使用sysfs_create_dir函数来创建,源代码如下所示:
4.2、内核对象的属性(struct attribute)对应于sysfs文件系统中的文本文件,可使用sysfs_create_file函数来创建,源代码如下所示:
sysfs文件系统中的二进制文件通过sysfs_create_bin_file函数来创建,符号链接文件通过sysfs_create_link函数来创建。
