Linux SysFs文件系统分析1(基于Linux6.6)---sysfs注册及挂载介绍
一、sysfs文件系统注册及挂载
1.1、Sysfs 文件系统概述
Sysfs 是一个虚拟文件系统,存在于 Linux 内核中,主要用于提供与内核内部信息的交互接口。它使用户空间的程序能够访问和操作内核中设备、驱动、内核参数等信息。Sysfs 提供了一个层次化的目录结构,允许用户和程序通过文件操作来访问和修改内核对象的状态。
在 Linux 中,Sysfs 通常挂载在 /sys
目录下。通过读取和写入 /sys
中的文件,用户和应用程序可以获取内核参数,控制内核行为,甚至配置硬件设备。
1.2、Sysfs 文件系统的功能
Sysfs 提供了如下功能:
- 访问内核对象和设备的属性:通过文件接口提供设备或驱动的状态信息、配置选项等。
- 动态修改内核参数:支持通过写入文件修改内核行为(如修改设备驱动的某些参数)。
- 系统信息:包括 CPU、内存、PCI、USB 设备等硬件信息。
- 驱动与设备的管理:设备驱动和内核模块与设备实例的动态绑定与管理。
1.3、文件系统的定义
Sysfs是一个内存文件系统,该文件系统主要在用户态展示系统硬件相关的设备、驱动、总线等层级关系。该文件系统将系统上的总线、设备、驱动等,按照不同的分类方式进行展示,应用层可对相应的文件属性值进行读写操作。目前sysfs按照device、bus、class、kernel、drivers、power等进行分类(具体分类如下图所示),其中devices中包含系统中所有的设备、drivers中包含所有已注册的驱动、bus中包括所有总线相关的信息、class中系统的设备类型(包括tty、net、rtc、gpio等)。
sysfs的超级块处理接口
fs/sysfs/mount.c
static struct file_system_type sysfs_fs_type = {
.name = "sysfs",
.init_fs_context = sysfs_init_fs_context,
.kill_sb = sysfs_kill_sb,
.fs_flags = FS_USERNS_MOUNT,
};
1.4、文件系统的注册及挂载
fs/sysfs/mount.c
int __init sysfs_init(void)
{
int err;
sysfs_root = kernfs_create_root(NULL, KERNFS_ROOT_EXTRA_OPEN_PERM_CHECK,
NULL);
if (IS_ERR(sysfs_root))
return PTR_ERR(sysfs_root);
sysfs_root_kn = kernfs_root_to_node(sysfs_root);
err = register_filesystem(&sysfs_fs_type);
if (err) {
kernfs_destroy_root(sysfs_root);
return err;
}
return 0;
}
在sysfs_init接口中实现文件系统的注册以及挂载,该接口的实现比较简单,如下流程所示,主要就是文件系统的注册以及文件系统的kern_mount(此时并没有真正挂载,但是已完成超级块、根root、根dentry、vfsmount的创建,待文件系统起来时,执行mount -t sysfs none /sys,在系统调用sys_mount时,通过调用do_add_mount实现将sysfs挂载至sys目录下。另外在sys_mount接口中,创建或者查找超级块是通过调用sb = sget(fs_type, sysfs_test_super, sysfs_set_super, flags, info);语句实现的,若对sysfs进行多次mount时,只创建一次超级块,因调用sysfs_test_super时对文件系统的私有变量判断相同,则无需再次创建超级块)。
针对sysfs文件系统的挂载进行一下分析,其处理流程图如下所示:
此处主要介绍sys_mount接口,该接口调用sget创建超级块,并调用sysfs_fill_super对sysfs的超级块进行设置,主要是设置超级块的操作接口指针、根dentry的操作接口等内容(sysfs_fill_super接口的定义如下流程图所示)。
1. sysfs 文件系统的注册
sysfs
文件系统的注册是通过内核代码中相应的初始化函数完成的。通常,sysfs
是由内核在启动时注册的,负责将内核中的各种信息暴露给用户空间。
注册过程概述:
-
内核启动时,sysfs 会被注册: 在内核启动过程中,
sysfs
文件系统的注册函数sysfs_init()
被调用。在这个函数中,内核会调用register_filesystem()
来注册sysfs
文件系统类型。具体的代码逻辑是由sysfs_init()
和相关的初始化模块执行的。 -
sysfs 注册时使用的文件系统结构体:
sysfs
的文件系统结构体是sysfs_type
,它通过file_system_type
结构体来定义文件系统的类型和操作。
static struct file_system_type sysfs_type = {
.name = "sysfs", // 文件系统的名称
.fs_flags = FS_REQUIRES_DEV, // 文件系统需要设备
.mount = sysfs_mount, // 挂载函数
.kill_sb = sysfs_kill_superblock, // 卸载文件系统时的清理函数
.get_sb = sysfs_get_superblock, // 获取超级块的函数
};
name
:文件系统的名称("sysfs")。fs_flags
:文件系统的标志,通常是FS_REQUIRES_DEV
,表示该文件系统需要设备。mount
:挂载函数,在sysfs
文件系统挂载时调用。kill_sb
:卸载文件系统时,清理超级块等资源。get_sb
:获取超级块的函数,通常在mount
过程中调用。
sysfs_init()
函数: 该函数在内核启动时执行,注册sysfs
文件系统。
static int __init sysfs_init(void)
{
int error;
error = register_filesystem(&sysfs_type); // 注册 sysfs 文件系统
if (error) {
pr_err("sysfs: cannot register sysfs filesystem\n");
return error;
}
pr_info("sysfs: registered the sysfs filesystem\n");
return 0;
}
register_filesystem(&sysfs_type)
:将sysfs_type
注册到内核中,使得sysfs
文件系统得以启用。
2. sysfs 文件系统的挂载
sysfs
文件系统默认在 Linux 启动时自动挂载。通常,它会被挂载到 /sys
目录,用户可以通过访问 /sys
下的文件来与内核交互,获取硬件信息、内核状态等数据。
挂载过程:
- 挂载点:默认情况下,
sysfs
会被挂载到/sys
目录。 - 挂载选项:在启动时,
sysfs
文件系统通常没有额外的挂载选项,它通过mount()
系统调用进行挂载。
通常在启动时,内核会自动将 sysfs
挂载到 /sys
目录,这通常是通过内核启动过程中的 mount
系统调用或 init
脚本来完成的。
通过 mount
系统调用挂载:
在内核启动时,sysfs
文件系统会被挂载到 /sys
。这个过程由内核的 mount
函数和相应的文件系统结构完成,通常不需要用户手动操作。
mount -t sysfs sysfs /sys
示例:挂载 sysfs
文件系统
在 init
或系统启动脚本中,通常会有类似以下的命令来挂载 sysfs
:
mount -t sysfs sysfs /sys
3. sysfs 文件系统的内容
sysfs
文件系统为用户提供了内核、硬件、驱动程序等信息的接口。通过访问 /sys
目录,用户可以查看和修改各种内核参数和硬件信息。
一些常见的 /sys
目录内容包括:
/sys/class
:存放设备的类,如块设备、字符设备等。/sys/devices
:硬件设备的树形结构,表示物理设备与内核之间的关系。/sys/kernel
:内核参数和信息。/sys/bus
:系统总线相关的信息。/sys/module
:内核模块的信息。
4. 卸载 sysfs 文件系统
在大多数情况下,sysfs
文件系统是不可卸载的,除非是卸载整个系统或关闭内核。通常,sysfs
会在内核关闭或系统关机时被卸载。要卸载 sysfs
,可以使用 umount
命令:
umount /sys
5. 总结
- 注册:
sysfs
文件系统在内核启动时通过register_filesystem()
函数注册。它通过file_system_type
结构体来定义文件系统的类型、挂载、卸载操作等。 - 挂载:
sysfs
文件系统默认挂载到/sys
目录,用户可以通过访问/sys
下的文件来与内核交互。 - 内容:
sysfs
文件系统提供了关于内核、硬件设备、内核配置等的信息,可以通过访问/sys
目录来获取。 - 卸载:一般情况下,
sysfs
文件系统不需要卸载,只有在关闭系统时才会被卸载。