Linux内核有什么之块设备驱动有什么第四回 —— 邂逅的三个文件系统之二:实际文件系统(1)

接前一篇文章:Linux内核有什么之块设备驱动有什么第三回 —— 邂逅的三个文件系统之一:devtmpfs

本文内容参考:

34 | 块设备(上):如何建立代理商销售模式?-趣谈Linux操作系统-极客时间

Linux内核——块设备总结_linux do_open-CSDN博客

【Linux驱动】块设备驱动(一)—— 注册块设备_创建块设备-CSDN博客

ext4 mount流程_ext4文件系统的mount option设置-CSDN博客

特此致谢!

上一回讲解了块设备驱动邂逅的第一个文件系统:devtmpfs。本回讲解块设备接下来邂逅的第二个文件系统,也是向这个块设备进行读写等操作,需要基于的主流文件系统,如ext2/3/4、XFS、F2FS等。

上回书讲过,块设备虽然与字符设备类似,也有打开、关闭、读写函数,但与字符设备不同,块设备常规操作不会直接打开/dev/下的块设备结点进行操作,而是会将此块设备(文件)mount到一个文件夹下面。

假设此块设备之前已被格式化为了某种文件系统的格式,以ext4为例。那么,mount操作实际调用的就是ext4文件系统相应的mount操作。来看一下ext4文件系统的mount流程。

上回书在讲devtmpfs的时候,讲到对devtmpfs文件系统的初始化是由devtmpfs_init函数完成的。再次贴出devtmpfs_init函数的代码,在drivers/base/devtmpfs.c中,如下:

/*
 * Create devtmpfs instance, driver-core devices will add their device
 * nodes here.
 */
int __init devtmpfs_init(void)
{
	char opts[] = "mode=0755";
	int err;
 
	mnt = vfs_kern_mount(&internal_fs_type, 0, "devtmpfs", opts);
	if (IS_ERR(mnt)) {
		pr_err("unable to create devtmpfs %ld\n", PTR_ERR(mnt));
		return PTR_ERR(mnt);
	}
	err = register_filesystem(&dev_fs_type);
	if (err) {
		pr_err("unable to register devtmpfs type %d\n", err);
		return err;
	}
 
	thread = kthread_run(devtmpfsd, &err, "kdevtmpfs");
	if (!IS_ERR(thread)) {
		wait_for_completion(&setup_done);
	} else {
		err = PTR_ERR(thread);
		thread = NULL;
	}
 
	if (err) {
		pr_err("unable to create devtmpfs %d\n", err);
		unregister_filesystem(&dev_fs_type);
		thread = NULL;
		return err;
	}
 
	pr_info("initialized\n");
	return 0;
}

与几乎所有的文件系统注册一样,在devtmpfs_init函数中会调用register_filesystem函数向Linux内核注册文件系统。devtmpfs文件系统类型描述符dev_fs_type定义如下(同文件中):

static struct file_system_type dev_fs_type = {
	.name = "devtmpfs",
	.mount = public_dev_mount,
};

那么与devtmpfs相类似和对应,在注册ext4文件系统的时候,也有其相对应的struct file_system_type实例。该实例为ext4_fs_type,在fs/ext4/super.c中,定义(更准确地说应该是初始化)如下:

static struct file_system_type ext4_fs_type = {
	.owner			= THIS_MODULE,
	.name			= "ext4",
	.init_fs_context	= ext4_init_fs_context,
	.parameters		= ext4_param_specs,
	.kill_sb		= ext4_kill_sb,
	.fs_flags		= FS_REQUIRES_DEV | FS_ALLOW_IDMAP,
};

这里要说一下,老版本Linux内核代码中,ext4_fs_type的值是这样的:

static struct file_system_type ext4_fs_type = {
    .owner = THIS_MODULE,
    .name = "ext4",
    .mount = ext4_mount,
    .kill_sb = kill_block_super,
    .fs_flags = FS_REQUIRES_DEV,
};

可以看到,老版本的ext4_fs_type代码中多了对mount成员的赋值,为ext4_mount函数。而新版本中已经去掉了。而老版本代码的ext4_mount函数代码为:

static struct dentry *ext4_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data)
{
    return mount_bdev(fs_type, flags, dev_name, data, ext4_fill_super);
}

而ext4_mount中所调用的mount_bdev函数,也在ext4乃至整个ext文件系统中找不到了。

说实在的,笔者对于内核这帮人没事闲的、老瞎改代码的行为是极其不满的。Linux内核源码本来就博大精深,其中很多内容需要花时间去深入研究。很多书或者博文将机制讲得比较透彻、也比较好理解了,但是再回来看新版内核代码,书或文章中所讲的内容已经没了,至于为什么去掉或者更改,就只能查阅www.kernel.org中的相应的内核提交说明。

以现在的ext4文件系统为例,刘超先生已经在其文章暨课程34 | 块设备(上):如何建立代理商销售模式?-趣谈Linux操作系统-极客时间中把老版本代码中的ext4的mount机制讲得比较透彻了,但是笔者一查新版内核(6.7版本),整个ext4_mount函数都没了。你就感觉,他们那个圈子想怎么变就怎么变、想怎么玩就怎么玩,不管大多数后来者和有志于入圈Linux文件系统尤其是ext文件系统的人。

这里,笔者就看看到底这帮维护者或贡献值为什么这样改变,这样做的好处和作用究竟是什么。访问以下链接:kernel/git/torvalds/linux.git - Linux kernel source tree,页面如下:

切换到“tree”选项下,页面如下:

进入到fs/ext4/super.c,页面如下:

切换到“log”选项下,页面如下:

找一下提交信息,看看ext4_mount函数是在什么时候被去掉的,在那次提交中被去掉的,原因究竟是什么。

经过仔细的定位查找,最终找到了具体的那一次提交:

这时间还挺早呢,距现在已经有2年多了。不过刘超的课程是2019年左右就上线了的,因此确实是在这次代码更新之前,还是老版本的代码。来看一下具体的提交说明,了解一下细节:

ext4: switch to the new mount api

ext4:切换至新的挂载api

Add the necessary functions for the fs_context_operations. Convert and rename ext4_remount() and ext4_fill_super() to ext4_get_tree() and ext4_reconfigure() respectively and switch the ext4 to use the new api.

为fs_context_operations添加了必要的函数。将ext4_remont()和ext4_fill_super()分别转换并重命名为ext4_get_tree()和text4_reconfigurate(),并将ext4切换为使用新的api。

One user facing change is the fact that we no longer have access to the entire string of mount options provided by mount(2) since the mount api does not store it anywhere. As a result we can't print the options to the log as we did in the past after the successful mount.

一个用户面临的变化是,我们不再能够访问mount提供的整个挂载选项字符串,因为挂载api不会将其存储在任何地方。因此,在成功挂载后,我们无法像过去那样将选项打印到日志中。

既然ext家族比较“蛋大”,非得玩点“幺蛾子”,而我们这个系列的主题又是块设备而非文件系统。因此,笔者不用ext4了、而是重新选择F2FS文件系统进行讲解,F2FS的代码还是按照老版内核的挂载机制来的。详情请看下回。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vscode通过多个跳板机连接目标机(两种方案亲测成功)

1、ProxyJump(推荐使用) 需要OpenSSH 7.3以上版本才可使用,可用下列命令查看: ssh -V ProxyJump命令行使用方法 ssh -J [email protected]:port1,[email protected]:port2 一层跳板机: ssh dst_usernamedst_ip -…

【Spring 篇】SpringMVC拦截器:给你的应用增添色彩

嗨,亲爱的小伙伴们!欢迎来到这段关于SpringMVC拦截器的奇妙之旅。今天我们要一探究竟,深入挖掘拦截器的神秘面纱,看看它是如何在你的应用中悄然发挥作用的。别怕,我会用最通俗易懂的语言,一步一步带你走进这…

Python之requests实现github模拟登录

文章目录 github 模拟登录前言模拟登录流程抓包操作查看登录表单的内容登录操作 模拟登录操作在 main函数的调用获得 auth_token调用/session接口登录处理检测登录是否成功 总结: github 模拟登录 前言 前面学习了requests模块的基础学习后,接下来做一个…

c++算法学习笔记 (8) 树与图部分

1.树与图的存储 &#xff08;1&#xff09;邻接矩阵 &#xff08;2&#xff09;邻接表 // 链式前向星模板&#xff08;数组模拟&#xff09; #include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N 100010, M …

GAMES104-现代游戏引擎 1

主要学习重点还是面向就业&#xff0c;重点复习八股和算法 每天早上八点到九点用来学习这个课程 持续更新中... 第一节 游戏引擎导论 第二节 引擎架构分层

jvm的垃圾回收器以及触发full gc的场景

JVM&#xff08;Java虚拟机&#xff09;的垃圾回收器有很多种&#xff0c;主要包括以下几种&#xff1a; Serial收集器&#xff1a;串行收集器是最古老、最稳定的收集器。它使用单个线程进行垃圾收集工作&#xff0c;在进行垃圾回收时会暂停所有用户线程。 ParNew收集器&#…

Mr-Robot1靶场练习靶场推荐小白入门练习靶场渗透靶场bp爆破wordpress

下载链接&#xff1a; Mr-Robot: 1 ~ VulnHub 安装&#xff1a; 打开vxbox&#xff0c;菜单栏----管理----导入虚拟电脑 选择下载完的ova文件&#xff0c;并修改想要保存的位置&#xff08;也可以保持默认位置&#xff09; 导入完成后可以根据自己的情况去配置网络链接方式 完成…

AI健身教练-引体向上-俯卧撑计数代码-仰卧起坐姿态估计-康复训练姿态识别-姿态矫正(附代码)

在AI健身应用中&#xff0c;通过关键点检测技术可以实现对用户动作的精准捕捉和分析&#xff0c;从而进行统计计数和规范性姿态识别。 统计计数&#xff1a;比如在做瑜伽、健身操等运动时&#xff0c;系统可以通过对人体关键点&#xff08;如手部、脚部、关节等&#xff09;的…

【Java设计模式】二十五、自定义Spring IoC

文章目录 1、IoC类的定义1.1 定义bean相关的pojo类PropertyValue1.2 定义MutablePropertyValues类1.3 定义BeanDefinition类 2、定义注册表相关类2.1 BeanDefinitionRegistry接口2.2 SimpleBeanDefinitionRegistry类 3、定义解析器相关类3.1 BeanDefinitionReader接口3.2 XmlBe…

还是了解下吧,大语言模型调研汇总

大语言模型调研汇总 一. Basic Language ModelT5GPT-3LaMDAJurassic-1MT-NLGGopherChinchillaPaLMU-PaLMOPTLLaMABLOOMGLM-130BERNIE 3.0 Titan 二. Instruction-Finetuned Language ModelT0FLANFlan-LMBLOOMZ & mT0GPT-3.5ChatGPTGPT-4AlpacaChatGLMERNIE BotBard 自从Cha…

FFmpeg转码参数说明及视频转码示例

-b : 设置音频或者视频的转码码率 -b:v 只设置视频码率 -b:a 只设置音频码率 -ab: 只设置音频码率, 默认码率大小为: 128k bit/s -g: 设置视频GOP大小,表示I帧之间的间隔,默认为12 -ar: 设置音频采样率,默认0 -ac: 设置音频通道数量 默认0 -bf: 设置连…

[自研开源] MyData 数据集成之数据过滤 v0.7.2

开源地址&#xff1a;gitee | github 详细介绍&#xff1a;MyData 基于 Web API 的数据集成平台 部署文档&#xff1a;用 Docker 部署 MyData 使用手册&#xff1a;MyData 使用手册 试用体验&#xff1a;https://demo.mydata.work 交流Q群&#xff1a;430089673 概述 本篇基于…

spring boot nacos注册微服务示例demo_亲测成功

spring boot nacos注册微服务示例demo_亲测成功 先安装好Nacos Nacos安装使用 创建Maven项目 结构如图 例如项目名为: test-demo 下面有个子模块: test-demo-data-process 父模块pom.xml <?xml version"1.0" encoding"UTF-8"?> <project …

【Flink SQL】Flink SQL 基础概念(三):SQL 动态表 连续查询

《Flink SQL 基础概念》系列&#xff0c;共包含以下 5 篇文章&#xff1a; Flink SQL 基础概念&#xff08;一&#xff09;&#xff1a;SQL & Table 运行环境、基本概念及常用 APIFlink SQL 基础概念&#xff08;二&#xff09;&#xff1a;数据类型Flink SQL 基础概念&am…

数据有噪声?滤它!Python数据滤波详解

文章目录 维纳滤波巴特沃斯滤波器中值滤波排序滤波 Python科学计算&#xff1a;数组&#x1f4af;数据生成&#x1f4af;数据交互&#x1f4af;微积分&#x1f4af;插值&#x1f4af;拟合&#x1f4af;FFT&#x1f4af;卷积 维纳滤波 信号经过系统之后&#xff0c;相当于进行…

简单的arduino实验理解串口通信(uart为例)独立硬件的信息交互

前言 接触过单片机的人都知道串口通信&#xff0c;可以通过另一个短文了解,其中入门的应该就是串口通信了。UART全拼的个人理解为通用的异步接收和发送。常见两根短线作为通信线&#xff0c;一般使用TXD和RXD标记。对于两块通信的芯片来说&#xff0c;接收和发送是相对的&…

Stargo 管理部署 Starrocks 集群

配置主机间 ssh 互信 ssh-copy-id hadoop02 ssh-copy-id hadoop03配置系统参数 ############################ Swap检查 ############################ echo 0 | sudo tee /proc/sys/vm/swappiness########################### 内核参数检查 ########################## echo…

PHP+golang开源办公系统CRM管理系统

基于ThinkPHP6 Layui MySQL的企业办公系统。集成系统设置、人事管理、消息管理、审批管理、日常办公、客户管理、合同管理、项目管理、财务管理、电销接口集成、在线签章等模块。系统简约&#xff0c;易于功能扩展&#xff0c;方便二次开发。 服务器运行环境要求 PHP > 7.…

2.3 物理层设备

2.3 物理层设备 &#xff08;一&#xff09;中继器 产生原因 由于存在损耗&#xff0c;在线路上传输的信号功率会逐渐衰减&#xff0c;衰减到一定程度时将造成信号失真&#xff0c;因此会导致接收错误。 中继器的功能 对信号进行再生和还原&#xff0c;对衰减的信号进行放大…

ArkTs的资源Resource类型怎么转为string

使用ResourceManager同步转换 请参看&#xff1a;ResourceManager.getStringSync9 例子&#xff1a; try { let testStr: string this.context.resourceManager.getStringSync($r(app.string.test).id); } catch (error) { console.error(getStringSync failed, error code…