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

news2024/11/18 13:53:08

背景

“文件”在文件系统之中,这是人人理解的概念。但“文件”之上还有一个文件系统?那岂不是成套娃了。但这个其实是可以的。这个就涉及到今天我们要讲的 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.coloradmin.cn/o/1838682.html

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

相关文章

2024年AIGC行业研究:多模态大模型与商业应用

2024年2月,OpenAI发布其首款视频生成模型Sora,用户仅需输入一段文字即可生成长达一分钟场景切换流畅、细节呈现清晰、情感表达准确的高清视频,与一年前的AI生成视频相比,在各维度均实现了质的提升。这一突破再次将AIGC推向大众视野…

JavaScript运行原理和执行过程

参考: https://www.cnblogs.com/hexrui/p/15939592.html 1、执行上下文栈(调用栈) GECGlobal Execution Context(GEC)被放入到ECS(Execution Context Stack,简称ECS)中 GEC开始执…

RLC防孤岛负载测试:市场前景展望

随着可再生能源的广泛应用,如太阳能和风能等,电力系统的结构正在发生深刻的变化。这种变化带来了许多新的挑战,其中之一就是如何有效地防止电力系统出现孤岛现象。为了解决这个问题,RLC防孤岛负载测试技术应运而生。 RLC防孤岛负载…

Git Extensions gui工具差异显示乱码

某些IDE例如KEIL等默认编码格式为GB2312,而git extensions默认utf-8,如果不想修改文件格式为utf-8的话就修改git extensions格式为GB2312。 默认是没有chines 这个选项的,我这里是已经添加好的。方法为上方工具栏->设置->Git->设置…

css 文字两端对齐

<body><div class"box"><p>姓名</p><p>性与别</p><p>家庭住址</p><p>how are you</p><p>hello</p><p>1234</p><p>1 2 3 4</p></div> </body> text-a…

走嵌入式方向有必要参加数模的比赛,涨一下见识吗?

在开始前刚好我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「嵌入式的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01;参加数模&#xff08;数学…

JAVA二手车交易二手车市场系统源码支持微信小程序+微信公众号+H5+APP

&#x1f697;二手车交易系统小程序&#xff1a;让买卖更轻松&#x1f50d; 功能介绍 我的粉丝、我的关注、获赞、访客 我的动态、认证中心、我的团队、开通会员 免费估值、买二手车、我要卖车、车型选择 每日上新、底价专区、精准筛选、附近展厅商 车辆的详细信息、拨打电…

前端高级架构师课程(总共111门课程,1150GB)

由阿里P8前端架构师亲自精心筛选整理的全网最新最具价值的前端进阶学习课程&#xff01; 培训机构原版教程&#xff01; 课程知识点和一线大厂完美匹配&#xff01; 所有课程资源完整成套&#xff0c;不残缺&#xff0c;不拼凑&#xff0c;不拆开乱发&#xff01; 这系列课程包…

UI自动化测试实战

目录 1 自动化测试流程2 项目介绍2.1 项目功能和技术2.2 项目简介2.3 用例设计2.4 编写代码2.4.1 公共方法2.4.2 抽取PO 2.5 视频 1 自动化测试流程 步骤&#xff1a; 需求分析挑选适合做自动化测试的功能【人力不足时&#xff0c;选择冒烟测试】设计并筛选测试用例搭建自动化…

JMemter镜像下载地址

腾讯软件源&#xff1a; https://mirrors.cloud.tencent.com/ JMemter镜像下载地址&#xff1a; https://mirrors.cloud.tencent.com/apache/jmeter https://mirrors.cloud.tencent.com/apache/jmeter/binaries

信创服务器操作系统的适配迁移分析

浅谈信创服务器操作系统的适配迁移 01 服务器操作系统迁移适配流程复杂 随着CentOS停服临近和红帽RHEL源码权限受限&#xff0c;服务器操作系统安全漏洞风险加剧。国内众多企业面临CentOS、REHL等系统升级替换的挑战。同时&#xff0c;出于安全、功能升级和合规需求&#xff0…

企业数据资产入表操作指引

在数字经济时代&#xff0c;数据已成为企业的关键生产要素&#xff0c;其管理和应用至关重要。数据资产入表操作涉及复杂的评估和管理过程&#xff0c;企业需要遵循合规性、真实性和透明性的原则。本指南旨在为企业提供系统化的操作指导&#xff0c;帮助实现数据资产的高效管理…

ARM32开发-fat_fs文件系统

FAT_FS 文件系统 FAT (File Allocation Table) 文件系统是一种广泛使用的基于磁盘的文件系统,尤其适用于小型嵌入式系统和存储卡。FAT_FS 就是一个专门针对 FAT 文件系统的开源实现。 FAT_FS 的主要特点 轻量级和高度可移植: FAT_FS 是一个非常轻量级的文件系统实现,占用资源少…

【JS重点15】原型对象概述

目录 一&#xff1a;构造函数缺陷 二&#xff1a;原型 1 原型是是什么 2 原型对象的作用 3 原型对象this指向问题 4 利用原型对象添加方法 给JS内置构造函数Array添加最大值方法 给JS内置构造函数Array添加求和方法 三&#xff1a;Constructor属性 四&#xff1a;如何…

应用无感,透明加密!麒麟信安商用密码改造方案助力密改合规

数字信息化时代&#xff0c;在产业政策与市场驱动的共同作用下&#xff0c;密码产品和应用服务需求日趋旺盛&#xff0c;合规、正确、有效地使用密码&#xff0c;是数据安全防护体系中的有效手段。但当前&#xff0c;各行各业信息系统中国产密码算法应用不合规、未使用、使用不…

使用Python实现自动化查询IP威胁情报

解决的问题 一名网络安全从业人员在做日常网络安全运营分析时&#xff0c;就从防火墙、IDP、WAF等安全设备的日志分析计算&#xff0c;基本都会面对成千上万条日志&#xff0c;好一点的可能会有态势感知之类安全产品提供辅助分析&#xff0c;如果没有的就只能单条进行分析&…

彻底卸载Ubuntu双系统

操作系统 文章目录 操作系统前言一、把开机启动项设为默认Windows启动二、删除Ubuntu系统分区三、删除开机启动引导项 前言 我们卸载Ubuntu双系统&#xff0c;可能出于以下原因&#xff1a; 1、Ubuntu系统内核损坏无法正常进入 2、Ubuntu系统分配空间不足&#xff0c;直接扩区…

如何规范信息技术课堂纪律

在信息技术课堂上&#xff0c;为了营造一个良好的学习环境&#xff0c;确保学生能够专注于学习任务&#xff0c;我们需要采取一系列措施来规范课堂纪律。以下是一些具体而详细的建议&#xff1a; 一、明确课堂规则 上课座位固定&#xff1a;学生的座位应固定&#xff0c;未经…

分享一个dnslog在线平台

DNSLog Platform 页面只有两个按钮&#xff0c;点击Get Subdomain可以随机生成一个dnslog 点击Refresh Record&#xff0c;刷新这个dnslog的记录。可以查看到这条dnslog的IP地址和创建时间。

vue elementui table给表格中满足条件的每一条记录添加计时器

需求&#xff1a; 在前端给表格中给满足条件的每一条记录增加一个计时器&#xff0c;用于计算工作时长。 1.数据库中存储的有每条记录的作业开始时间&#xff0c;将当前时间和作业开始时间计算一个差值&#xff0c;作为作业时长的初始值&#xff1b; 2.把满足条件的每条记录绑…