Linux SysFs文件系统分析2

Linux SysFs文件系统分析2(基于Linux6.6)---sysfs相关结构体介绍

一、相关结构体说明

从结构体之间的联系,建立对sysfs文件系统实现框架的感性认识,以便我们更好的理解sysfs文件系统。先来看下这些结构体的关系,如下所示主要包括kset、kobject、kref、sysf_dirent、kobj_type、sys_ops、sysfs_elem_dir、sysfs_elem_symlinks、sysfs_elem_attr、sysfs_elem_bin_attr结构体。主要包括sysfs与设备模型关联的结构体、sysfs文件系统目录及文件建立相关、sysfs文件操作相关的结构体等几大部分。

如上图所示,一个kset结构体变量包括一类kobject的集合,而针对一个kset而言,且也是一个目录,因此其也有相应的kobject,而关于kset的引用计数,直接使用kobject->kref实现引用计数的功能。而针对一个kobject而言,其也有相应的方法,即kobj_type,该方法中包括kobject的释放以及show/store接口,还包括默认的属性参数等。

二、sysfs与设备模型关联的结构体

与设备模型相关的结构体主要为kset、kobject、kref、sysfs_dirent等,其中kobject表示内核对象,定义了内核对象后,则针对每一个设备类型、驱动类型、总线类型等,均可用一个内核对象表示,在sysfs中一个kobject即代表一个目录,针对sysfs的文件,是没有对应的kobject,kobject仅表示目录。而在设备模型中,针对设备、驱动以及总线而言,均会有对应的内核对象,而针对总线而言,其还会包含kset变量,并通过该kset变量的list成员变量,链接bus下所有具体已注册总线的内核对象(kobject)。通过这几个变量,就实现了与设备驱动模型的关联。

这些结构体的关联如下:

struct kobject定义说明

kobject的定义,主要包括对象命令、引用计数、该kobject所属的kset等。

include/linux/kobject.h 

struct kobject {
	const char		*name;
	struct list_head	entry;
	struct kobject		*parent;
	struct kset		*kset;
	const struct kobj_type	*ktype;
	struct kernfs_node	*sd; /* sysfs directory entry */
	struct kref		kref;

	unsigned int state_initialized:1;
	unsigned int state_in_sysfs:1;
	unsigned int state_add_uevent_sent:1;
	unsigned int state_remove_uevent_sent:1;
	unsigned int uevent_suppress:1;

#ifdef CONFIG_DEBUG_KOBJECT_RELEASE
	struct delayed_work	release;
#endif
};

struct kset定义说明

主要包括属于该kset的kobject的链表头、该kset对应的内核对象、kset对应的事件处理接口等

include/linux/kobject.h 

struct kset {
	struct list_head list;
	spinlock_t list_lock;
	struct kobject kobj;
	const struct kset_uevent_ops *uevent_ops;
} __randomize_layout;

struct kref定义

该结构体就是一个原子变量,用于kobject的引用计数。

include/linux/kref.h 

struct kref {
	refcount_t refcount;
};

struct kobj_type定义

该结构体主要是kobject对应的释放接口以及属性操作接口(属性操作接口,主要用于该对象下文件的读写操作)

include/linux/kobject.h  

struct kobj_type {
	void (*release)(struct kobject *kobj);
	const struct sysfs_ops *sysfs_ops;
	const struct attribute_group **default_groups;
	const struct kobj_ns_type_operations *(*child_ns_type)(const struct kobject *kobj);
	const void *(*namespace)(const struct kobject *kobj);
	void (*get_ownership)(const struct kobject *kobj, kuid_t *uid, kgid_t *gid);
};

struct sysfs_ops定义

 include/linux/sysfs.h

struct sysfs_ops {
	ssize_t	(*show)(struct kobject *, struct attribute *, char *);
	ssize_t	(*store)(struct kobject *, struct attribute *, const char *, size_t);
};

该结构体主要包括show、store接口指针,其中show、store主要用于属性对应文件的读与写接口,这两个接口需要输入的参数包括kobject、attribute结构体对应的变量。

struct attribute结构体说明

针对上述的结构体变量attribute,系统中各子模块可通过创建包含该结构体变量attribute的私有变量,从而实现针对具体属性的show/store接口的调用。

以struct bus_attribute 结构体变量为例进行简要说明。针对bus目录而言,在进行总线的注册时,其kobject对象的struct kobj_type变量定义为bus_ktype,其中定义了bus目录对应的show/store接口为bus_attr_show/bus_attr_store,而bus对应的属性结构体为bus_attribute,包含了struct attribute成员变量、show/store接口指针(这个show/store接口即为具体文件的处理接口),当在bus目录下创建文件时,则会创建bus_attribute结构体的变量,而在bus_attr_show/bus_attr_store接口中会根据传入的attribute结构体变量,从而获取bus_attribute结构体类型的变量,然后就调用bus_attribute结构体类型变量的show/store接口,从而实现对具体文件的show/store操作。

include/linux/device/bus.h 

struct bus_attribute {
	struct attribute	attr;
	ssize_t (*show)(const struct bus_type *bus, char *buf);
	ssize_t (*store)(const struct bus_type *bus, const char *buf, size_t count);
};

三、sysfs文件系统目录及文件建立相关

在 Linux 6.x 版本中,sysfs_dirent 结构体确实已经被移除,并且通过重构的方式改进了 sysfs 文件系统的实现。要理解这一点,首先需要了解 Linux 内核在处理 sysfs 时的变动。

1. sysfs_dirent 移除的背景

在早期的 Linux 内核中,sysfs_dirent 结构体是 sysfs 文件系统的一个核心数据结构,它代表 sysfs 文件系统中的文件和目录。这个结构体与内核对象(kobject)相关联,负责管理文件的操作(如读写)以及维护文件层次结构。

然而,随着内核的发展,特别是内核文件系统架构的不断改进,内核对 sysfs 的实现方式进行了简化和优化。为了减少复杂性和提高效率,sysfs_dirent 结构体被移除,取而代之的是对 dentry 结构体和 kobject 的更紧密结合和改进。

2. sysfs 文件系统在 Linux 6.x 的实现

在 Linux 6.x 中,sysfs 的实现更加直接与 VFS(虚拟文件系统)和 kobject 结合,减少了对专门的 sysfs_dirent 结构体的依赖。其基本思路是利用 dentrykobject 来进行管理,并通过对内核对象的注册与暴露来实现对 sysfs 的支持。

核心概念:

  • dentry(目录项)dentry 是虚拟文件系统(VFS)中用于表示目录项的结构体。在 Linux 内核中,dentry 是文件路径解析、缓存和访问的核心结构。sysfs 文件系统的目录项(如文件、目录等)通过 dentry 来管理,而不再依赖专门的 sysfs_dirent

  • kobject(内核对象)kobject 是 Linux 内核中一个通用的对象模型,它提供了内核对象与用户空间的交互方式,包括 sysfs 文件的暴露。每个 sysfs 文件都与一个 kobject 关联,表示该文件对应的内核对象。

  • sysfs 的整合: 在 Linux 6.x 中,sysfs 文件系统的目录结构依然存在,但它是通过 kobject 的生命周期管理和 dentry 的高效查找机制来实现的。每个 kobject 都有一个关联的 dentry,并通过 sysfs 文件系统接口暴露其属性。

主要改动:

  1. sysfs 通过 kobjectdentry 配合: 在新的实现中,kobject 负责将内核对象暴露给 sysfs,而 dentry 负责实际的目录项操作。sysfs 文件不再通过专门的 sysfs_dirent 来表示,而是通过 dentry 的层次结构与内核对象(kobject)进行关联。

  2. 简化操作: 由于 dentry 已经是文件系统中目录项的标准表示方式,因此无需再引入额外的 sysfs_dirent 数据结构,这大大简化了内核代码的复杂性,同时也提升了文件系统操作的效率。

  3. 减少冗余数据结构sysfs_dirent 的移除减少了不必要的结构体,减少了内存的占用,并使得内核中 sysfs 文件的管理更加高效。

3. 新的 sysfs 管理方式

在 Linux 6.x 中,sysfs 的管理更加直接,主要依靠 kobjectdentry 来完成以下任务:

  • 内核对象的创建和销毁: 通过 kobject 来创建、销毁内核对象,并通过相应的 kobject 接口管理对象生命周期。每个内核对象通常会在 /sys 目录下有对应的文件和目录。

  • 文件的暴露: 当一个 kobject 被注册到 sysfs 时,相应的文件将通过 dentrykobject 的关联被创建在 /sys 目录中。每个文件的内容通过 sysfs_ops 中定义的 showstore 方法来处理。

  • 目录项层次结构: 使用 dentry 实现 sysfs 的目录层次结构。在 Linux 6.x 中,每个目录项都是一个 dentry 对象,它代表文件系统中的一个文件或目录。目录项的创建、删除和层次结构的管理通过 dentry 来完成,而不再需要额外的 sysfs_dirent

4. 代码示例

在 Linux 6.x 中,sysfs 文件的创建通常如下:

#include <linux/kobject.h>
#include <linux/sysfs.h>
#include <linux/module.h>

static struct kobject *example_kobj;

static ssize_t example_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
    return sprintf(buf, "Hello, sysfs!\n");
}

static struct kobj_attribute example_attribute = __ATTR(example_file, 0444, example_show, NULL);

static int __init sysfs_example_init(void)
{
    int retval;

    example_kobj = kobject_create_and_add("example", kernel_kobj);
    if (!example_kobj)
        return -ENOMEM;

    retval = sysfs_create_file(example_kobj, &example_attribute.attr);
    if (retval)
        kobject_put(example_kobj);

    return retval;
}

static void __exit sysfs_example_exit(void)
{
    kobject_put(example_kobj);
}

module_init(sysfs_example_init);
module_exit(sysfs_example_exit);
MODULE_LICENSE("GPL");

在这个示例中,内核模块通过 kobject_create_and_add 创建了一个新的内核对象,并通过 sysfs_create_file 创建了一个新的 sysfs 文件。内核对象的属性通过 kobj_attributeshow 函数来暴露,而文件本身由 dentry 管理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值