【Linux kernel 文件系统入门及渐进 1 -- sysfs 介绍】

news2024/9/24 0:18:17

文章目录

    • 1.1 Sysfs 介绍
      • 1.1.1 kobject 产生背景
      • 1.1.2 主要的数据结构
      • 1.1.3 数据结构实现
    • 1.2 attribute 的功能概述
      • 1.2.1 struct attribute 实现
      • 1.2.2 attribute 文件的创建
      • 1.2.3 attibute 文件的 read 和 write

1.1 Sysfs 介绍

Sysfs 是一个基于 RAM 的文件系统,它和 ** kobject** 一起,可以将 kernel 的数据结构导出到用户空间,以文件目录结构的形式,提供对这些数据结构(以及数据结构的属性)的访问支持。
在这里插入图片描述

每一个 kobject,都会对应 sysfs 中的一个目录。因此在将 kobject 添加到 kernel时,create_dir 接口会调用 sysfs 文件系统的创建目录接口,创建和 kobject 对应的目录。kobject 也是组成设备模型的基本结构。

接下来看下 Linux kobject 形成的历史背景及作用。

1.1.1 kobject 产生背景

Linux 设备模型的核心是使用 Bus、Class、Device、Driver 四个核心数据结构,将大量的、不同功能的硬件设备(以及驱动该硬件设备的方法),以树状结构的形式,进行归纳、抽象,从而方便 kernel的统一管理。

而硬件设备的数量、种类是非常多的,这就决定了 kernel 中将会有大量的有关设备模型的数据结构。这些数据结构一定有一些共同的功能,需要抽象出来统一实现,否则就会不可避免的产生冗余代码。这就是 kobject 诞生的背景。

目前为止, kobject 主要提供如下功能:

  • 通过 parent 指针,可以将所有 kobject 以层次结构的形式组合起来。
  • 使用一个引用计数(reference count),来记录 kobject被引用的次数,并在引用次数变为0时把它释放。
  • 和 sysfs 虚拟文件系统配合,将每一个 kobject 及其特性,以文件的形式,开放到用户空间

1.1.2 主要的数据结构

在描述数据结构 ** kobject** 之前,有必要说明一下 kobject, ksetktype 这三个概念:

  • kobject 是基本数据类型,如上文所说,每个 kobject 都会在 "/sys/“ 文件系统中以目录的形式出现。
  • ktype 代表 kobject 的属性操作集合, 由于通用性,多个 kobject 可能共用同一个属性操作集,因此把 ktype 独立出来了 , 例如:kobject 结构体中有 struct kref 字段用于对 kobject 进行引用计数,当计数值为 0 时,就会调用 kobj_type 中的 release 函数对 kobject 进行释放。
  • kset 是一个特殊的 kobject(因此它也会在 "/sys/“ 文件系统中以目录的形式出现),它用来集合相似的 kobject(这些 kobject 可以是相同属性的,也可以不同属性的),比如 devices_kset ,在 sysfs 中对应目录 “/sys/devices”, 注册设备或驱动时就将 kobject 添加到对应的 kset 中;

通过下图来看这三者的关系: (网图1)
在这里插入图片描述
来自网图 2:
在这里插入图片描述

1.1.3 数据结构实现

kernel 源代码中, kobject 由如下两个文件实现:

  • include/linux/ kobject.h
  • lib/ kobject.c

其中 kobject.h 为 kobject 的头文件,包含所有的数据结构定义和接口声明, kobject.c 为核心功能的实现。

先看下 struct kobject 的实现:

struct  kobject {
      const char *name;
      struct list_head    entry;
      struct  kobject     *parent;
      struct kset         *kset;
      struct kobj_type    *ktype;
      struct sysfs_dirent *sd;
      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;
};
  • name: kobject 的名称,同时也是 sysfs 中的目录名称。由于 kobject 添加到kernel 时,需要根据名字注册到 sysfs中,之后就不能再直接修改该字段。如果需要修改 kobject 的名字,需要调用 kobject_rename 接口,该接口会主动处理 sysfs 的相关事宜;
  • entry:用于将 kobject 加入到 kset 中的 list_head;
  • parent:指向 parent kobject,以此形成层次结构,在 sysfs 就表现为目录结构);
  • kset:该 kobject 属于的 kset,可以为 NULL。如果存在,且没有指定 parent,则会把 kset 作为 parent;
  • ktype:该 kobjectt 属于的 kobj_type。每个 kobject 必须有一个 ktype,否则 kernel 会提示错误;
  • sd:该 kobject 在 sysfs 中的表示,指向 kernelfs_node;sysfs 中的每一个目录或者文件都有一个 kernel_node 来描述,就像 VFS 中的 inode 一样;
  • kref:"struct kref” 类型(在 include/linux/kref.h 中定义)的变量,为一个可用于原子操作的引用计数;
  • state_initialized:指示该 kobject 是否已经初始化,以在 kobject 的 init,put,add 等操作时进行异常校验;
  • state_in_sysfs:指示该 kobject 是否已在 sysfs 中呈现,以便在自动注销时从 sysfs 中移除;
  • state_add_uevent_sent/state_remove_uevent_sent:记录是否已经向用户空间发送 add uevent,如果有,且没有发送 remove uevent,则在自动注销时,补发 remove uevent,以便让用户空间正确处理。
  • uevent_suppress:如果该字段为 1,则表示忽略所有上报的 uevent 事件。

Uevent 提供了“用户空间通知”的功能实现,通过该功能,当内核中有 kobject 的增加、删除、修改等动作时,会通知用户空间。

再看下 struct kset 的实现:

 struct kset {
      struct list_head list;
      spinlock_t list_lock;
      struct  kobject kobj;
      const struct kset_uevent_ops *uevent_ops;
 };
  • list/list_lock:用于保存该kset下所有的 kobject的链表;
  • kobj:该 kset 自己的 kobject(kset 是一个特殊的 kobject,也会在 sysfs 中以目录的形式体现);
  • uevent_ops:该 kset 的 uevent 操作函数集。当任何 kobject 需要上报 uevent 时,都要调用它所从属的 kset 的 uevent_ops,添加环境变量,或者过滤 event(kset可以决定哪些 event 可以上报)。因此,如果一个 kobject 不属于任何 kset时,是不允许发送 uevent 的。

最后看下 struct ktype 的实现:

struct kobj_type {
      void (*release)(struct  kobject *kobj);
      const struct sysfs_ops *sysfs_ops;
      struct attribute **default_attrs;
      const struct kobj_ns_type_operations *(*child_ns_type)(struct  kobject *kobj);
      const void *(*namespace)(struct  kobject *kobj);
  • release:通过该回调函数,可以将包含该种类型 kobject 的数据结构的内存空间释放掉;
  • sysfs_ops:该种类型的 kobject 的 sysfs 文件系统接口
  • default_attrs:该种类型的 kobject 的 atrribute 列表(所谓 attribute,就是 sysfs 文件系统中的一个文件),将会在 kobject 添加到内核时,一并注册到sysfs中;
  • child_ns_type/namespace:和文件系统(sysfs)的命名空间有关。

1.2 attribute 的功能概述

在 sysfs 中,为什么会有 attribute 的概念呢
其实它是对应 kobject 而言的,指的是 kobject 的 “属性” 。我们知道,sysfs 中的目录描述了 kobject,而 kobject 是特定数据类型变量(如 struct device)的体现。因此 kobject 的属性,就是这些变量的属性。它可以是任何东西,名称、一个内部变量、一个字符串等等。而 attribute 在 sysfs 文件系统中是以文件的形式提供的,即: kobject 的所有属性,都在它对应的 sysfs 目录下以文件的形式呈现。这些文件一般是可读、写的,而 kernel 中定义了这些属性的模块,会根据用户空间的读写操作,记录和返回这些 attribute 的值。

所谓的 attibute,就是内核空间和用户空间进行信息交互的一种方法。例如某个 driver 定义了一个变量,却希望用户空间程序可以修改该变量,以控制 driver 的运行行为,那么就可以将该变量以 sysfs attribute 的形式开放出来。

1.2.1 struct attribute 实现

Linux 内核中,attribute 分为普通的 attribute 和二进制 attribute,这里主要介绍普通的 attribute, 如下:

struct attribute {
      const char     *name;
      umode_t         mode;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
      bool ignore_lockdep:1;
      struct lock_class_key   *key;
      struct lock_class_key   skey;
 #endif
};

name: 表示文件名称;
mode: 表示文件模式;
其它的字段: 都是内核用于debug kernel Lock的。

attribute 生成的 sysfs 文件,只能用字符串的形式读写

说完基本概念,我们要问两个问题
1. kernel 怎么把 attribute 变成 sysfs 中的文件呢?
2. 用户空间对 sysfs 的文件进行的读写操作,怎么传递给 kernel 呢?

1.2.2 attribute 文件的创建

在内核中,sysfs 的属性文件一般都是由 xxx_ATTR 系列的宏来实现, 如:

  • 对设备的使用 DEVICE_ATTR
  • 对总线使用 BUS_ATTR
  • 对驱动使用 DRIVER_ATTR
  • 对类别(class)使用 CLASS_ATTR

例如:Linux 会使用 DEVICE_ATTR 宏,在 /sys/devices/ 下面生成 attribute 文件节点,驱动开发工程师只需要实现 showstore 函数即可。然后在 userspace 就能通过 catecho 命令来对 “/sys/” 下创建出来的属性文件进行读写操作, 从而实现和底层的交互。

在 linux 内核中,attibute 文件是由 fs/sysfs/file.c 中 sysfs_create_file 通过kobject 创建:

static inline int __must_check sysfs_create_file(struct kobject *kobj,
  						 				const struct attribute *attr)
{
		return sysfs_create_file_ns(kobj, attr, NULL);
}

下面的 3 个函数内部都会调用到 sysfs_create_file

  • device_create_file: 为设备创建 sys 的节点(drivers/base/core.c);
  • bus_create_file : 为总线创建 sys 的节点;
  • driver_create_file : 为驱动创建 sys 的节点。

DEVICE_ATTR() 宏定义:
DEVICE_ATTR() 定义位于 include/linux/device.h 中, 定义如下所示:

#define DEVICE_ATTR(_name, _mode, _show, _store)	\
	struct device_attribute dev_attr_##_name =		\	
						 __ATTR(_name, _mode, _show, _store)

其中 _mode 定义如下:

  • 400 拥有者能够读,其他任何人不能进行任何操作;
  • 644 拥有者都能够读,但只有拥有者可以编辑;
  • 660 拥有者和组用户都可读和写,其他人不能进行任何操作;
  • 664 所有人都可读,但只有拥有者和组用户可编辑;
  • 700 拥有者能够读、写和执行,其他用户不能任何操作;
  • 744 所有人都能读,但只有拥有者才能编辑和执行;
  • 755 所有人都能读和执行,但只有拥有者才能编辑;
  • 777 所有人都能读、写和执行。

当然也可以用 S_IWUSR (用户可写),S_IRUSR(用户可读)等宏代替。

下面用具体代码展示如何创建 attribute 文件:

static DEVICE_ATTR(my_test, S_IWUSR | S_IRUSR, show_my_device, \
				   show_my_device, set_my_device);

static ssize_t show_my_device(struct device *dev, 
							  struct device_attribute *attr, 
							  char *buf)
{
	return sprintf(buf, "test result:0x%x\n", 0xffff);
}

static ssize_t set_my_device(struct device *dev,
							 struct device_attribute *attr,
							 const char *buff, size_t count)
{
	unsigned int input, ret_val;
	
	if (sscanf(buff, "%x", &input) < 0x1) {
		PR_ERR(storing information failed\n);
		return count;
	}
	/* TODO */
	return count;
}

最后会将宏展开为:

struct device_attribute dev_attr_my_test ={
	.attr   = {.name = "my_test", .mode = S_IWUSR|S_IRUSR },
	.show   = show_my_device,
	.store  = set_my_device,
}

然后再通过 device_create_file() 创建上面 my_test 设备文件。

	ret = device_create_file(dev, &dev_attr_my_test);
	if (ret < 0) {
		dev_err(dev, "failed to create sysfs!\n");
		return ret;
	}

函数 device_create_file 会调用到 sysfs_add_file_mode_ns,最后是调用kernfs_new_node() 创建了一个 kernfs_node 结构。sysfs 中的每一个目录或者文件都有一个 kernfs_node 来描述,就像 VFS 中的 inode 一样。

sysfs 和 kobject 实现为两套独立的框架。一个 kobject 在 sysfs 中表现为一个目录,属性在 sysfs 中表现为一个文件。kernfs_node->priv 指向 kobjectkobject->sd指向 kernfs_node,这实现了 kobject 框架和 sysfs 的连接;总的来说:

  • sysfs 实现了文件/目录结构层次的管理;
  • kobject框架提供了底层文件/目录的操作方法。
    在这里插入图片描述

1.2.3 attibute 文件的 read 和 write

通过上节内容我们知道了如何创建 attribute 文件,那文件操作的接口在哪里呢

所有的文件系统,都会定义一个 struct file_operations 变量,用于描述本文件系统的操作接口,sysfs 也不例外,从 linux/fs/kernfs/file.c 看看 sysfs 相关的代码逻辑:

const struct file_operations kernfs_file_fops = {
    .read       = kernfs_fop_read,
    .write      = kernfs_fop_write,
    .llseek     = generic_file_llseek,
    .mmap       = kernfs_fop_mmap,
    .open       = kernfs_fop_open,
    .release    = kernfs_fop_release,
    .poll       = kernfs_fop_poll,
    .fsync      = noop_fsync,
};

attribute 文件的 read 操作,会由 VFS 转到 kernfs_file_fops 的 read。
在这里插入图片描述

推荐阅读
http://www.wowotech.net/linux_kenrel/ kobject.html
http://www.wowotech.net/device_model/dm_sysfs.html
https://zhuanlan.zhihu.com/p/530283012
https://blog.csdn.net/chenying126/article/details/78079942/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/140929.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何优化.so mmap内存占用

1&#xff09;如何优化.so mmap内存占用 ​2&#xff09;模拟器下物理碰撞失效 3&#xff09;Unity RenderTexture的释放在安卓上并不能使GL内存完全回落 4&#xff09;数字人中&#xff0c;怎么做到胡子固定在嘴巴皮肤上 这是第319篇UWA技术知识分享的推送。今天我们继续为大家…

docker容器入门介绍

一、什么是docker容器 容器&#xff08;Container&#xff09;是基于镜像创建的运行实例&#xff0c;一个容器中可以运行一个或多个应用程序&#xff08;jdk开发的java应用 程序&#xff09;。 Docker 可以帮助你构建和部署容器&#xff0c;你只需要把自己的应用程序或者服务打…

对外投资数据集

一、2009-2018年各省省际对外非金融类直接投资流量情况数据来源&#xff1a; 中国商务年鉴2、时间跨度&#xff1a;2009-2018年3、区域范围&#xff1a;全国各省份二、2003&#xff0d;2018 OFDI对外直接投资存流量&#xff08;分国家&#xff09;与分省份对外直接投资存流量1、…

一个在关键路径上面隐藏了11个月的BUG:DragonOS进程切换查错

前言的前面 DragonOS是一个从0开始研发内核及用户态环境的&#xff0c;独立自主的&#xff0c;面向服务器领域的开源操作系统&#xff0c;提供Linux兼容性。 官网&#xff1a;https://DragonOS.org 代码仓库&#xff1a;GitHub - fslongjin/DragonOS: 一个64位的操作系统。A…

基于jsp+sevlet+mysql实现用户登陆和增删改查功能

基于jspsevletmysql实现用户登陆和增删改查功能一、系统介绍二、功能展示1.用户登陆2.用户列表3.查询用户信息4.添加用户信息5.修改用户信息6.删除用户信息三、其它系统四、获取源码一、系统介绍 系统主要功能&#xff1a; 用户登陆、添加用户、查询用户、修改用户、删除用户 …

用javascript分类刷leetcode4.贪心(图文视频讲解)

什么是贪心算法 贪心法&#xff0c;又称贪心算法&#xff0c;贪婪算法&#xff0c;在对问题求解时&#xff0c;总是做出在当前看来最好的选择&#xff0c;期望通过每个阶段的局部最优选择达到全局最优&#xff0c;但结果不一定最优 适用场景&#xff1a;简单的说&#xff0c;…

手把手YOLOv5输出热力图

环境要求 我的版本是YOLOV5 7.0 先看结果&#xff1a; 结果仅供参考 具体步骤一&#xff1a; 首先配置好YOLO V5环境 这个采用pip install requirements即可 具体配置环境可以看我其他的博客有详细介绍 GPU环境自己配置 步骤二&#xff1a; 运行YOLO 没问题&#xff0c;输…

Excel表格的导入导出——EasyExcel

参考视频 csdn参考地址 一、导入依赖 <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.0.5</version> </dependency>二、实体类 方式一&#xff1a;Excel Property&#xff08;&…

Kubernetes Pod 底层实现原理

文章目录前言一、探索 Container1.1 设置实验环境&#xff08;playground&#xff09;1.2 探索容器的 namespace1.3 探索容器的 cgroupsCheck the memory limit.二、探索 Pod2.1 设置实验环境&#xff08;playground&#xff09;2.2 探索 Pod 的容器2.3 探索 Pod 的命名空间2.4…

UDP协议重点总结(附实例)

文章目录前言一、网络的原生情况二、UDP协议2.1 UDP的特点2.1.1 不可靠性2.1.2 无连接&#xff08;不是缺点&#xff09;2.1.3 面向数据报&#xff08;优点&#xff09;2.1.4 缓冲区2.1.5 大小受限2.2 UDP协议端格式2.3 关于校验和2.4 基于UDP的应用层协议三、UDP总结&#xff…

P2279 [HNOI2003]消防局的设立

[HNOI2003]消防局的设立题目描述2020 年&#xff0c;人类在火星上建立了一个庞大的基地群&#xff0c;总共有 n 个基地。起初为了节约材料&#xff0c;人类只修建了 n-1 条道路来连接这些基地&#xff0c;并且每两个基地都能够通过道路到达&#xff0c;所以所有的基地形成了一个…

HTML5本地存储详解

html5 本地存储。前言一、localStorage 对象二、sessionStorage 对象三、localstorage 与 cookie 的区别四、localStorage 和 sessionStorage 二者的区别总结前言 ☀️本地存储是指在客户端存储数据&#xff0c;HTML5 为我们提供了两种 API&#xff0c;分别是 localStorage 与 …

算法是如何炼成的?

一、算 法 简 史算法可以追溯到古代埃及人和古希腊人使用的算术方法。在古代埃及&#xff0c;人们使用简单的加减法来解决基本的数学问题&#xff0c;而在古希腊&#xff0c;人们开始使用更加复杂的算术方法&#xff0c;比如平方、立方、平方根和立方根。随着数学的发展&#x…

css元素转换(旋转函数、rotateX 和 rotateY 的使用、移动函数、缩放函数、过渡、动画)详解

文章目录旋转函数rotateX 和 rotateY 的使用移动函数缩放函数过渡transition-timing-function 属性动画旋转函数 在 CSS3 中&#xff0c;使用 rotate 函数能够让指定的元素对象绕原点旋转&#xff0c;主要在二维空间内进行操作。 其语法格式如下所示&#xff1a; transform: …

【C++常用算法】STL基础语法学习 | 查找算法

目录 ●find ●find_if ●adjacent_find ●binary_ search ●count ●count_if ●find 1.功能描述&#xff1a; 查找指定元素&#xff0c;如果找到则放回指定元素的迭代器&#xff0c;若未找到则返回结束迭代器。 2.查看find定义下底层代码的函数原型&#xff1a; 3.…

Day849.ThreadLocal线程本地存储模式 -Java 性能调优实战

ThreadLocal线程本地存储模式 Hi&#xff0c;我是阿昌&#xff0c;今天学习记录的是关于ThreadLocal线程本地存储模式的内容。 民国年间某山东省主席参加某大学校庆演讲&#xff0c;在篮球场看到十来个人穿着裤衩抢一个球&#xff0c;观之实在不雅&#xff0c;于是怒斥学校的…

用于安全医疗保健系统的基于机器学习的可伸缩区块链架构

文章目录背景相关技术简介区块链扩张性电子病历数据安全安全医疗保健的架构基于可扩展区块链架构的机器学习概述基于可扩展区块链架构的机器学习工作流程小结摘要从3.0到4.0的工业革命已经改变了医疗保健环境。患者电子健康记录(EHR)与医学研究机构共享&#xff0c;用于临床研究…

12月榜单丨B站UP主排行榜(飞瓜数据B站)发布!

飞瓜轻数发布2022年12月飞瓜数据UP主排行榜&#xff08;B站平台&#xff09;&#xff0c;通过充电数、涨粉数、成长指数三个维度来体现UP主账号成长的情况&#xff0c;为用户提供B站号综合价值的数据参考&#xff0c;根据UP主成长情况用户能够快速找到运营能力强的B站UP主。飞瓜…

Python:python简介

1&#xff1a;特点 一种解释型&#xff0c;面向对象&#xff0c;动态数据类型的开源高级程序设计语言 其特点就是&#xff1a;优雅&#xff0c;明确&#xff0c;简单&#xff0c;完善的基础代码库和大量的第三方库。 2&#xff1a;解释VS解释 3&#xff1a;应用场景 python…

基于androidstudio校园快递APP系统的设计与实现

1.课题背景及研究的目的和意义 1.1 课题背景 在其发展速度可谓一日千里的电子商务时代&#xff0c;大学生群体已成为网络购物群体中不可或缺的一部分。因此&#xff0c;高校师生对网购的需求也愈来愈强烈&#xff0c;校园快递的问题也成为了焦点&#xff0c;其中校园快递代理…