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 是个好工具,可以用来查看文件上的二进制内容。

来源:奇伢云存储 

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

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

相关文章

Spring底层原理之bean的加载方式三 用注解声明配置类 以及@Configuration 和 @Component 的区别

bean的加载方式三 用注解声明配置类 我们之前用组件扫描加上注解定义bean 实现了bean的加载 当我们又会发现这个配置文件过于繁琐 我们可以写一个类 不是配置文件而是配置类 我们接下来只需要把这句话的功能写到 配置类里面 这样书写就行 package com.bigdata1421.config;…

全球社交的连接者:Facebook的跨文化影响力

在当今高度数字化和全球化的时代,社交网络不仅仅是人们交流和连接的工具,更成为促进全球文化交流和理解的重要平台。作为全球最大的社交网络之一,Facebook不仅连接了数十亿用户,还在跨文化交流和社会互动方面发挥着重要作用。本文…

【遇到的问题】集群上查看gpu的使用情况

流程: 查看bme_cpu所有节点的详细情况scontrol show node bme_gpu[12-23] 下面这个看起来分配出去较少 查看bme_cpu空闲节点sinfo -p bme_gpu -o "%n %G %C %m %e NVIDIAA10080GBPCIe 卡 gpu 13看起来最少 在命令中选择这个节点 #!/bin/bash #SBATCH -J rati…

山洪灾害无线预警广播系统解决方案

一、国家政策 2021年水利部印发了《全国山洪灾害防治项目实施方案(2021-2023年)》,提出“到2023年,山洪灾害防治体系进一步健全,监测预警能力进一步提升,努力补齐山洪灾害防治当前存在的明显短板”的建设目…

思科交换机基本配置命令

01进入特权模式enable switch>enable switch# 02进入全局配置模式configure terminal switch>enable switch#configure terminal switch(conf)# 03交换机命名hostname aptech2950以aptech2950为例 switch>enable switch#configure terminal switch(conf)#hostname apt…

创建App

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 在Django项目中,推荐使用App来完成不同模块的任务,通过执行如下命令可以启用一个应用程序。 python manage.py startapp app…

allegro 如何替换过孔?

操作步骤如下 1.选择操作对象(需要替换的过孔),右键–>Repace……–>Selected…… 2.在弹出的窗口中选择最终需要的过孔既可以

怎么用表单二维码来收集信息?二维码收集信息的制作教程

现在通过二维码来收集用户信息的方式在很多场景中都有应用,随着毕业季的到来学校也开始用这种方式来收集学生的个人信息,学生只需要扫描生成二维码,根据问题填写对应的内容,将数据统计到专门的后台中存储,实现数据的快…

k8s设置pod资源请求和限制

设置资源请求和限制 实验目标: 学习如何为 Pod 设置资源请求和限制,以优化集群资源分配。 实验步骤: 创建一个 Deployment,并设置 CPU 和内存的资源请求和限制。使用 kubectl describe 命令查看资源分配情况。观察资源限制对 P…

IMU应用于颈部健康监测

随着电脑成为日常工作的必备工具,长时间使用电脑导致的颈部疼痛问题日益受到关注。近日,一项创新研究利用IMU开发了一种新型监测系统,用来监测电脑使用者的颈部姿势和疼痛情况。 在为期两天的实验中,8名办公室工作者分别在静态和…

详细介绍iutils.dll丢失的多个解决方法,一键快速修复丢失的iutils.dll文件

当用户遭遇“iutils.dll缺失”的提示时,这通常预示着依赖该库文件的程序将面临启动失败或功能受限的风险。DLL(Dynamic Link Library,动态链接库)文件无疑占据了核心地位。这些文件就如同建筑师手中的蓝图,为软件的构建…

Linux内核测试技术

Linux 内核是Linux操作系统的核心部分,负责管理硬件资源和提供系统调用接口。随着 Linux 内核的不断发展和更新,其复杂性和代码规模也在不断增加。因此,确保内核的稳定性和可靠性变得尤为重要。内核测试技术是实现这一目标的关键手段。本文将…

数据库管理工具Navicat v17全新发布——释放全新的建模能力

Navicat是一个可连接多种数据库的管理工具,它可以让你以单一程序同时连接到MySQL、Oracle及PostgreSQL数据库,让管理不同类型的数据库更加的方便。 接下来我们将为大家介绍Navicat v17中的一些主要亮点,其释放的全新建模能力、最大化数据可见…

厄瓜多尔海外媒体发稿:大舍传媒-媒体宣发投放需要什么条件?

一、厄瓜多尔媒体 厄瓜多尔媒体有: EcuapaginasEcuapuntoViviendaya 这些媒体都是厄瓜多尔当地颇具影响力的新闻**和社交媒体平台,为广告主和品牌提供了一个广阔的宣传空间。 二、大舍传媒介绍 大舍传媒是一家专业的海外媒体宣发投放,致…

Linux的免交互

交互:我们发出指令控制程序的运行,程序在接收到指令之后按照指令的效果做出对应的反应。 免交互:间接的通过第三方的方式把指令传送给程序,不用直接的下达指令。 1、here document免交互 ere document免交互:是命令…

如何绘制网络安全运营的“谷歌地图”?

正如Google Maps(谷歌地图)彻底改变了驾车出行时的导航模式一样,通过流程映射绘制一张指导网络安全运营的“电子地图”,可以彻底改变组织理解和管理网络安全运营工作的方式。 现代企业网络安全运营的核心并不是部署防火墙和杀毒软…

浅析MySQL-基础02

目录 MySQL一行记录是怎么存储的? MySQL的数据存放在哪? 表空间文件的结构是怎么样的? InnoDB行格式有哪些? Compact行格式是啥样的? 记录的额外信息 1、变长字段长度列表 2、NULL值列表 3、记录头信息 记录…

【AI大模型】ChatTTS——颠覆传统,赋能未来的文本到语音技术

文章目录 一、项目介绍二、代码解释三、从技术角度进行分析四、技术细节与实现五、优缺点分析六、应用场景分析七、未来展望八、结论 一、项目介绍 随着人工智能技术的不断进步,语音合成(TTS)技术得到了飞速发展。ChatTTS项目作为一个开源的…

分享一个好用的图幅号计算器

如果在你的工作中会分幅处理地图数据,也许这个好用的图幅号计算器能对你有所帮助。 你只需要在该工具中输入经纬度坐标,就可以为你计算出各个比例尺下的图幅号,你可以在文末查看该工具的领取方法。 一个好用的图幅号计算器 该图幅计算器工…

关于无人机——你知道有哪些种类?

随着无人机相关技术的飞速发展,无人机的种类也越来越多。也正由于无人机的多样性,从不同的角度考量会有不同的分类方法: 按照飞行平台构型分类,无人机可分为固定翼无人机、旋翼无人机、无人飞艇、伞翼无人机、扑翼无人机等。 按…