Linux 式套娃,把“文件系统”安装在一个“文件”上?

背景

“文件”在文件系统之中,这是人人理解的概念。但“文件”之上还有一个文件系统?那岂不是成套娃了。但这个其实是可以的。这个就涉及到今天我们要讲的 loop 设备。

很多童鞋在学习 Linux 的文件系统时,涉及到对磁盘设备的格式化,挂载等操作,但苦于没有一个真实的硬盘,一时不知道如何实践。这种时候就可以使用一个文件来模拟块设备。这就是 loop 设备的作用。我们借助 loop 设备,可以让一个文件被当做一个块设备来访问。

举个例子,我们在 ext4 的文件系统目录下创建了一个 minix_test.img 文件,把它当作一个块设备,在上面格式化 minix 的文件系统,并挂载到 /mnt/minix 上。示意图如下:

图片

这种方式有两个很明显好处:

不需要真实的硬盘,就可以格式化、挂载、测试文件系统。

可以近距离的观察文件系统对块设备的使用,比如如何划分 inode 区域、数据区域、位图区域等。这些都将反馈到文件上。

如何使用 loop 设备?

接下来看下如何使用 loop 设备。我们将会用一个普通文件上格式化成 minix 文件系统,然后挂载到 Linux 目录树上。我们使用 loop 设备有两种方式:

  1. 一种是直接 mount 带上 -o loop 的参数。这种省去了显式创建 loop 设备的过程,步骤简单。
  2. 另一种方式是先显式的创建 loop 设备,该 loop 设备绑定一个文件,并提供了块设备的对外接口。我们就可以把这个 loop 设备当作一个普通的块设备文件,进行格式化,然后挂载到目录上。
方式一:mount -o loop

用 mount 挂载文件系统的时候,指定某个文件以 loop 设备的方式进行挂载。具体操作如下:

首先,我们创建一个 1GiB 的文件:

dd if=/dev/zero of=./minix_test.img bs=1M count=1024

然后,我们在这个文件上进行 minix 文件系统的格式化:

mkfs.minix ./minix_test.img

最后,我们用 loop 设备的方式进行挂载:

mount -o loop ./minix_test.img /mnt/minix/

这样挂载成功之后,就可以在 /mnt/minix 下进行操作了。该目录挂载的是 minix 类型的文件系统。minix 文件系统是一个磁盘类型的文件系统,它的数据是会写到磁盘进行持久化。所以,我们在这个 /mnt/minix 目录下做的任何操作,这些都会反映到 ./minix_test.img 这个文件上。这个文件就像磁盘一样,在这个上面承载了一个文件系统的数据。

可以尝试在 /mnt/minix 目录下创建一个文件,然后用 hexdump 工具查看 minix_test.img 的内容变化。如下:

# 在 minix 文件系统之上创建一个文件,并写入一个字符串
echo "hello world" >> /mnt/minix/hello.txt# 查看 minix_test.img 的内容
hexdump -C ./minix_test.img

如果你对 minix 文件系统的分区熟悉的话,就可以明显看到 minix 是如何在 minix_test.img 文件上划分的 inode 区域、数据区域、位图区域等。

方式二:先创建 loop 设备,再挂载使用

这种方式稍微步骤多一点,但其实更容易让人理解其中原理。实际的效果和方式一是等价的。我们可以使用 losetup 命令来管理 loop 设备。

首先,我们创建一个 1GiB 的文件:

dd if=/dev/zero of=./minix_test.img bs=1M count=1024

然后,我们在这个文件上进行 minix 文件系统的格式化:

mkfs.minix ./minix_test.img

再然后,创建和使用 loop 设备:

# 方式一:假定 /dev/loop5 是空闲可用的 loop 设备,下面把 /dev/loop5 和 minix_test.img 关联起来
losetup /dev/loop5 ./minix_test.img# 方式二:可以简单一点,让 losetup 命令自动找到一个空闲的 loop 设备,然后进行关联
losetup --find --show ./minix_test.img

创建完 loop 设备之后,可以用 losetup 命令列举当前所有的 loop 设备,和它们关联的文件。

最后,把 loop 设备挂载到目录上:

# 假设上一个步骤创建的是 /dev/loop5 
mount /dev/loop5 /mnt/minix

这种方式挂载的文件系统和方式一本质上是一样的。

mount 和 losetup 等命令的源代码都在 util-linux 开源库中,感兴趣的童鞋们可以自行查看。

什么是 loop 设备?

本质上来讲,loop 设备是块设备的一种特殊的驱动实现。接下来我们来简单看下 loop 设备的基本原理。

loop 设备的原理

loop 就是一种特殊的块设备驱动。loop 设备是一种 Linux 虚拟的伪设备,它和真实的块设备不同,它并不代表一种特定的硬件设备,而仅仅是满足 Linux 块设备接口的一个虚拟设备。它的作用就是把一个文件模拟成一个块设备。

loop 设备它是怎么模拟的块设备?

loop 设备的代码位于 Linux 的 drivers/block/loop.c 中。在这个文件中,它定义了块设备驱动的接口。

块设备驱动的编程范式:

  1. 首先,要分配并初始化一个 gendisk 结构体,这是内核代表块设备的核心结构体。它包含了与磁盘相关的信息,loop 设备作为一种特殊的块设备驱动,这个自然是不能少的。
  2. 然后,初始化一个请求队列。块设备使用请求队列来管理对设备的 I/O 请求。文件系统调用 submit_bio 的调用时,最终就是把请求投递到驱动的队列中。
  3. 然后,请求处理函数。这个很容易理解,队列里的请求总是要处理的,每个块设备驱动都可以自定义处理方式。
  4. 最后,块设备操作表(block_device_operations),这个将包含对设备的操作方法,比如打开,读写控制等。

loop 设备如何关联到后端“文件” ?

用户态的处理( losetup 或 mount )
  • 打开后端“文件”,拿到文件描述符。
  • 打开 loop 设备文件,拿到 loop 设备的描述符。
  • 调用 ioctl 把这两个关联起来ioctl(dev_fd, LOOP_CONFIGURE, &lc->config)
内核的处理
  • ioctl 的系统调用对应调用 loop 中的 lo_ioctl 函数。

对应了 block_device_operations 的 ioctl 方法。

  • 当设置参数为 LOOP_CONFIGURE 的时候,会调用 loop_configure 来分配和初始化 loop 设备。
  • loop_configure
  • 获取到后端“文件”的句柄,也就是 struct file* 结构。获取到之后,会做一些校验工作。然后初始化 loop 设备相关的结构体,队列等。

  • 最关键的当然还是把 loop 设备和后端“文件”的句柄关联起来:lo->lo_backing_file = file; 这样的话,等到读写 loop 设备的时候,就可以把请求转发过去。

loop 设备的请求来自于哪里?

loop 设备它对外就是一个块设备,如果在这个之上创建了文件系统,并被当作块设备挂载到目录上之后,那么它的请求来自于它之上的文件系统。

文件系统调用 submit_bio ,把请求投递到块层的队列中。每一个块层的设备它都需要实现一个入队的处理,以供 submit_bio 的流程中调用。

static const struct blk_mq_ops loop_mq_ops = {.queue_rq       = loop_queue_rq,.complete = lo_complete_rq,
};

loop 设备实现的入队方法就是 loop_queue_rq 。文件系统调用 submit_bio 之后最终就会调用到 loop_queue_rq 这个函数。

> loop_queue_rq> loop_queue_work

loop_queue_work 函数会把请求放到一个 lo->workqueue 队列中,每一个 loop 设备都对应有这么一个队列。在创建设备文件的时候会同步生成。

loop 设备如何把请求传递给后端文件?

loop 设备还有一个名为 loop_workfn 的函数,是专门用来处理投递到该设备的请求。

> loop_workfn> loop_handle_cmd> do_req_filebacked

在 do_req_filebacked 函数中,会按照不同的命令类型来处理请求,比如,写请求会调用 lo_write_simple ,读请求会调用 lo_read_simple 等。

在这个 lo_write_simple  函数中,就会调用 lo_write_bvec ,把写请求写入关联的“文件”中。

static int lo_write_simple(struct loop_device *lo, struct request *rq,loff_t pos)
{// lo_backing_file 代表当前 loop 设备关联的文件ret = lo_write_bvec(lo->lo_backing_file, &bvec, &pos);
}

在 lo_write_bvec 中,调用的是 vfs_iter_write 函数来进行写入。这个函数其实是 VFS 层的一个封装函数,所以相当于就是从顶层调用后端文件的写操作。

在 lo_write_bvec 中,最关键的是 lo->lo_backing_file 这个文件句柄的获取。它的类型是 struct file* ,代表了一个内核打开的文件。即该 loop 设备关联的文件。它的赋值就是在 loop 设备创建的时候。

Linux 套娃之后,I/O 链路是什么样的?

现在来看下,当我们使用 loop 设备,来挂载一个 minix 文件系统,它的 I/O 路径又会是怎么样的呢?

假定创建的 minix_test.img 位于一个 ext4 文件系统。

应用程序 -> 系统调用 -> vfs -> minix 文件系统 -> 块层 -> loop 设备 -> 绑定的文件 ->  vfs -> ext4 -> ...

示意图如下:

图片

loop 设备的典型应用有哪些?

其实,loop 设备在很多场景下我们都用过。以下是比较典型的例子:

  • 系统模拟和测试:可以使用 loop 设备来模拟不同的存储配置,无需使用物理硬件,就可以进行软件测试或系统配置实验。
  • 文件系统开发:开发者可以使用 loop 设备来挂载文件系统,从而方便地测试和调试新的文件系统。
  • ISO 映像挂载:Loop 设备还常用于挂载 ISO 文件,无需刻录到物理介质上,使其内容可直接访问。
  • 加密磁盘:loop 设备还能和一些加密技术(如dm-crypt)结合,因为 loop 设备可以绑定几乎任意类型的文件,这就给了人们无限的想象空间。我们可以创建一个加密的磁盘镜像,增强数据安全。

其实,Linux 的套娃还远不止这些。举个例子,loop 设备绑定的文件,它可能也是抽象出来的一个文件,比如是一个网络文件系统抽象出来的文件。那这条 I/O 链路就更长了。只要你敢想,在 Linux 中,存在无限套娃的可能。

总结

  • 没有磁盘也想玩磁盘类文件系统?可以,用 loop 设备。只要你有文件,Linux 的 loop 设备都可以把文件变成一个“块设备”。
  • loop 设备就是一种特殊的块设备驱动。
  • 文件之上的的文件系统的增、删、改、查的 I/O 请求,它都将落到文件上。这个可以让我们近距离的观察到文件系统是如何管理磁盘的。
  • hexdump 是个好工具,可以用来查看文件上的二进制内容。

来源:奇伢云存储 

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

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

相关文章

一个轻量级的TTS模型实现

1.环境 python 版本 3.9 2.训练数据集 本次采用LJSpeech数据集,百度网盘下载地址 链接:https://pan.baidu.com/s/1DDFmPpHQrTR_NvjAfwX-QA 提取码:1234 3.安装依赖 pip install TTS 4.工程结构 5代码部分 decoder.py import torch f…

汇编基础之使用vscode写hello world

汇编语言(Assembly Language) 概述 汇编语言(Assembly Language)是一种低级编程语言,它直接对应于计算机的机器代码(machine code),但使用了更易读的文本符号。每台个人计算机都有…

iOS 18 Siri 升级之后都有哪些改变?

新界面 首先最显著的改变就是 Siri 的界面不同了,之前的界面是在打开 Siri 之后会出现一个圆形图案,而在 Siri 升级之后变成了屏幕边缘发出亮光。 来源:Apple 可在任意位置使用 苹果的生成式人工智能 Apple Intelligence 将为 Siri 提供支…

注意力机制和Transformer模型各部分功能解释

文章目录 Transformer1、各部分功能解释2、通过例子解释a.输入预处理位置编码b.Encoder 的处理c.Decoder的输入Decoder的工作流程d.输出预测总结 Attention代码和原理理解 Transformer 运行机理: (1)假设我们需要进行文本生成任务。我们将已…

Springboot集成SSE消息推送

SSE介绍 SSE(Server-Sent Events)的全称是服务器推送事件,它是一种基于 HTTP 协议的实时通信技术,用于在客户端和服务器之间建立持久、单向的链接,允许服务器向客户端发送异步消息。 了解 websocket 的小伙伴&…

SAP BC 换了logo后,其他人的logo都已经换了,但是其中有一台就是PRD 显示DEV的logo,从smw0上下载的是PRD

昨天终于发现是缓存的问题 GUI登录后 选项-本地数据-缓存 删除本地缓存文件,问题解决了

机器学习课程复习——聚类算法

Q:什么是硬聚类,什么是软聚类? 如果一个样本只能属于一个类,则称为硬聚类(hard clustering); 如果一个样本可以属于多个类,则称为软聚类(soft clustering)。 Q:聚类和分类的区别? 聚类分类学习类型无监督学习方法 不需要事先标记的数据 通过发现数据中的模式或结构来组…

sprintboot依赖管理和自动配置

springboot依赖管理和自动配置 依赖管理和自动配置依赖管理什么是依赖管理修改自动仲裁/默认版本号 starter场景启动器starter场景启动器基本介绍官方提供的starter第三方starter 自动配置自动配置基本介绍SpringBoot自动配置了哪些?如何修改默认配置如何修改默认扫描包结构re…

深入解析 iOS 应用启动过程:main() 函数前的四大步骤

深入解析 iOS 应用启动过程:main() 函数前的四大步骤 背景描述:使用 Objective-C 开发的 iOS 或者 MacOS 应用 在开发 iOS 应用时,我们通常会关注 main() 函数及其之后的执行逻辑,但在 main() 函数之前,系统已经为我们…

C++及cmake语法介绍

c/cmake学习 文章目录 c/cmake学习1. c1.1 基本模型1.1.1 for循环1.1.2 main函数1.1.2 带参数函数编译函数 2. CMAKE2.1 相关命令2.1.1 编译基本命令2.1.2 动态库静态库编译2.1.3 消息输出2.1.4 cmake变量常见参数1. 设置构建类型2. 设置编译器标志3. 指定编译器4. 设置安装路径…

机器学习_PCA

目录 一、概念 二、原理 三、步骤 四、实战 1、数据处理——转rgb为灰度图像 2、手动实现pca降维 3、查看信息保留数量 4、调用第三方库实现pca降维 五、小结 引入: 当说黄河五路和渤海三路交叉口的时候,这些路就类似于我们说的坐标系。而城市中的…

高等数学笔记(三):导数

一、导数概念 1.1 导数的定义 1.1.1 函数在一点处的导数与导函数 1.1.2 单侧导数 1.2 导数的几何意义 1.3 函数可导性与连续性的关系 二、函数的求导法则 2.1 函数的和、差、积、商的求导法则 2.2 反函数的求导法则 2.3 复合函数的求导法则 2.4 基本求导法则与导数公式 三…

必看!!! 2024 最新 PG 硬核干货大盘点(上)

PGConf.dev(原名PGCon,从2007年至2023年)首次在风景如画的加拿大温哥华市举办。此次重新定位的会议带来了全新的视角和多项新的内容,参会体验再次升级。尽管 PGCon 历来更侧重于开发者,吸引来自世界各地的资深开发者、…

深入理解并打败C语言难关之一————指针(5)(最终篇)

前言: 仔细一想,小编已经把指针的大部分内容都说了一遍了,小编目前有点灵感枯竭了,今天决定就结束指针这一大山,可能很多小编并没有提到过,如果有些没说的小编会在后续博客进行补充道,不多废话了…

服务器数据恢复—NTFS文件系统下双循环riad5数据恢复案例

服务器存储数据恢复环境: EMC CX4-480存储,该存储中有10块硬盘,其中有3块磁盘为掉线磁盘,另外7块磁盘组成一组RAID5磁盘阵列。运维人员在处理掉线磁盘时只添加新的硬盘做rebuild,并没有将掉线的硬盘拔掉,所…

ARCGIS 如何对河流等线条图形进行Smooth处理——具有多个断点高阶版

1.线转点折点(注意!很重要,不是线转点) 2.点转线步骤 ## 3 线的融合 2.1 新建Filed 》短精度类型》利用选择工具的 线文件。全选同一条河流点,进入Tabel的选择界面。给同一条河赋值同一个值。 大功告成!…

文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《计及多类型储能调频容量动态申报的电能量与调频市场联合出清方法研究》

本专栏栏目提供文章与程序复现思路,具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

深入探究RTOS的任务调度

阅读引言: 此文将会从一个工程文件, 一步一步的分析RTOS的任务调度实现, 这里选用FreeRTOS分析, 别的也差不多的, 可能在细节上有少许不一样。 目录 1, 常见嵌入式实时操作系统 2, 任务调度的…

【机器学习】第11章 神经网络与深度学习(重中之重)

一、概念 1.神经元模型 (1)神经网络的基本组成单位 (2)生物上,每个神经元通过树突接受来自其他被激活神经元的信息,通过轴突释放出来的化学递质改变当前神经元内的电位。当神经元内的电位累计到一个水平时…

Kubernetes Dashboard

Dashboard Dashboard 的项目网站,可以查看说明文档和基本的使用情况。 下载yaml wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.6.0/aio/deploy/recommended.yaml注意需要修改镜像,不然可能会拉去不下来镜像 cat recommended.yaml…