何为挂载(mount)?

在操作系统的Lab中,我们用bximage创建了一个1.44mb的软盘镜像img
然后为了将我们编译好的汇编程序写入该镜像,使用了如下命令:

sudo mount -o loop XX.img /mnt/floppy
sudo cp 汇编程序 /mnt/floppy
sudo umount /mnt/floppy

这其中发生了什么?何为挂载mount?

想要了解挂载过程的细节就需要知道文件系统和分区的知识。

分区

分区是一种对磁盘在逻辑上进行的划分。早期的磁盘最多只能支持四个分区。随着磁盘容量的增加,需要增加其分区数量,但是受制于分区表的大小和兼容旧的程序,不能直接增加,而是选一个分区标记为特殊的拓展分区,然后将该分区进一步划分为子分区,这种子分区被称为逻辑分区,这样就实现了将磁盘分成>4个分区
拓展分区本身是不能被直接使用的,必须进一步划分成逻辑分区,再使用逻辑分区。逻辑分区的编号从5开始,因为1-4号需要给旧的分区方式留着
那些不可进一步划分子分区的磁盘分区被称为主分区。一个磁盘最多有1个拓展分区。
在这里插入图片描述
分区表扫描的工作稍微复杂一些,需要以 MBR 引导扇区为入口,遍历所有主分区,然后找到总扩展分区,在其中递归遍历每一个子扩展分区,找出逻辑分区。由于涉及到分区的管理, 因此给每个分区起个名字,

Linux 设备命名方案。 Linux中所有的设备都在/dev/目录下,硬盘命名规则是[x]d[y][n],其中只有字母 d 是固定的,其他带中括号的字
符都是多选值,下面从左到右介绍各个字符。
x 表示硬盘分类,硬盘有两大类, IDE 磁盘和 SCSI 磁盘。 h 代表 IDE 磁盘, s 代表 SCSI 磁盘,故 x取值为 h 和 s。
d 表示 disk,即磁盘。
y 表示设备号,以区分第几个设备,取值范围是小写字符,其中 a 是第 1 个硬盘, b 是第 2 个硬盘,依次类推。
n 表示分区号,也就是一个硬盘上的第几个分区。分区以数字 1 开始,依次类推。

综上所述, sda 表示第 1 个 SCSI 硬盘, hdc 表示第 3 个 IDE 硬盘,
sda1 表示第 1 个 SCSI 硬盘的第 1个分区, hdc3 表示第 3 个 IDE 硬盘的第 3 个分区。

每个设备文件名和设备号是一一对应的。很多对设备的操作都需要使用设备号
(设备号=主设备号*256 + 次设备号)
内核维护着一个特殊的数据结构,用来存放设备号与设备的关系。在安装设备时,应该给设备申请一个设备号,使系统可以明确设备对应的设备号。设备驱动程序中的很多功能,是通过设备号来操作设备的。
磁盘是块设备的一种,而块设备有分区的概念,此时,次设备号既表示一个设备,也表示一个分区。

文件系统

一个文件系统通常占据块设备(硬盘)的一个分区。本质上是通过额外的数据结构建立一种使用数据块的方式。
一个文件系统通常要包含这样几个区域:

超级块+inode表+数据区
为了我们的目标,下面只是大致介绍要用到的内容。
超级块中存放一些描述文件系统本身的信息:inode个数,所在的设备号,被挂载到目录对应的inode…
inode表:每个inode都记录相当于是文件数据的目录,其中有一个数组i_zone[] 记录了此文件数据所在的块号。另外还有两个字段:一个代表此inode对应文件当前是否被使用【引用数】,另一个表示目录项中有几个项指向此inode【链接数】
数据区就是文件数据实际所在的位置

根据一次间接块号中找出的磁盘块中存放的内容是更多的磁盘块号
根据二次间接块号第二次找到的内容仍是其它磁盘块号
在这里插入图片描述

目录的实现,一个目录存放的数据包含文件名和对应的inode
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

挂载

所谓挂载就是将一个存放着文件系统分区与根文件系统(第一个默认被挂载的文件系统)中的某个目录对应的inode关联起来,并将其标记为已经挂载了文件系统,使之与一般的inode区分开
在这里插入图片描述

linux0.11中关于挂载的实现是sys_mount()
我们先来讨论正常的物理设备的挂载:
sys_mount接受两个参数,一个是设备名,另一个是要挂载到的目录名
操作系统在初始化是已经完成了对设备名和设备号等信息的注册
因此将设备名传给namei() ,以返回该设备文件对应的inode
再根据inode的字段判断是否为块设备文件的inode,若是则其数组i_zone[0]中存放的是其设备号。
到此,第一个小步骤完成:取得块设备的设备号
在这里插入图片描述
第二步就是将该设备(分区)和当前文件系统中目的目录的inode关联起来
通过函数read_super()根据块设备号得到其文件系统的元信息:超级块。
其中有一个关键字段是此文件系统挂载的inode指针,因此将目的目录的inode地址赋给该字段即完成了挂载。
在这里插入图片描述

不过还有一个问题没有解决。上面的这个过程是物理设备(分区)的挂载,其中的关键是使用了设备号。这些物理设备的分区信息当然在操作系统初始化时被读取并保存下来,可是在OS Lab中使用的 mount -o loop XX.img /mnt/floppy 又是怎么实现挂载虚拟软盘镜像的呢?
软盘镜像是一种特殊的文件——档案,它包含了一个完整文件系统的格式,操作系统不可能自动地将其识别为一个设备文件,进而它不可能被自动地分配设备号。这就要借助命令中的-o loop 将软盘镜像和一个假设备文件绑定,再将其按一般的物理设备文件那样挂载

在 linux 中, loop device 就是指 /dev/loop0, /dev/loop1, /dev/loop2 … 这些设备, 它们是虚假的设备, 不像 /dev/sda 在主机里物理存在
ok, 明白了什么是 loop device, 也明白了档案是什么, 那么到底如何把一个档案挂载到某个目录下呢?

实际上 loop mount 采取了一个瞒天过海的方式, 它先将这个档案映射到某个 loop device 上, 像这样:

# losetup /dev/loop0 xxxx.iso

通过这种方式来欺骗mount命令, 让mount命令以为 /dev/loop0 上面真的有设备. 这时运行mount就行了:

# mount -t iso9660 /dev/loop0 /path/to/mount/point

这么看起来, 当你想挂载某一个档案的时候(比如某个 iso), 你首先得把这个档案和某一个 loop device 关联起来, 使用
losetup 命令. 然后使用 mount 命令将这个 loop device 设备挂载到某个目录上.
实际上不必这样,mount命令自身其实就有一个能把这两步合并的功能, 那就是这样:

# mount -t iso9660 -o loop /dev/loop0 /path/to/mount/point

https://blog.csdn.net/binks_/article/details/70799134

如下是挂载一个虚拟软盘镜像的后半流程:
在这里插入图片描述

下面是linux0.11中的sys_mount() 源码

 安装(新) 文件系统(系统调用)。
// 参数 dev_name 是设备文件名, dir_name 是安装到的目录名, rw_flag 被安装文件系统的可
// 读写标志。将被加载的地方必须是一个目录名,并且对应的 i 节点没有被其他程序占用。
// 若操作成功则返回 0,否则返回出错号。

 int sys_mount(char * dev_name, char * dir_name, int rw_flag)
 {
 	struct m_inode * dev_i, * dir_i;
 	struct super_block * sb;
 	int dev;

// 首先根据设备文件名找到对应的 i 节点,以取得其中的设备号。对于块特殊设备文件,设备
// 号在其 i 节点的 i_zone[0]中。另外,由于文件系统必须在块设备中,因此如果不是块设备
// 文件,则放回刚取得的 i 节点 dev_i,返回出错码。
 	if (!(dev_i=namei(dev_name)))
 		return -ENOENT;
 	dev = dev_i->i_zone[0];
 	if (!S_ISBLK(dev_i->i_mode)) {
 		iput(dev_i);
 		return -EPERM;
 	}
// OK,现在上面为了得到设备号而取得的 i 节点 dev_i 已完成了它的使命,因此这里放回该设
// 备文件的 i 节点。接着我们来检查一下文件系统安装到的目录名是否有效。于是根据给定的
// 目录文件名找到对应的 i 节点 dir_i。 如果该 i 节点的引用计数不为 1(仅在这里引用),
// 或者该 i 节点的节点号是根文件系统的节点号 1,则放回该 i 节点返回出错码。另外,如果
// 该节点不是一个目录文件节点,则也放回该 i 节点,返回出错码。因为新文件系统只能安装
// 在一个目录名上。
 	iput(dev_i);
 	if (!(dir_i=namei(dir_name)))
 		return -ENOENT;
 	if (dir_i->i_count != 1 || dir_i->i_num == ROOT_INO) {
 		iput(dir_i);
 		return -EBUSY;
 	}
 	if (!S_ISDIR(dir_i->i_mode)) { // 安装点需要是一个目录名。
 		iput(dir_i);
 		return -EPERM;
 	}
// 现在安装点也检查完毕,我们开始读取要安装文件系统(新文件系统) 的超级块信息。一个文件
// 系统的超级块会首先从超级块表中进行搜索,如果不在超级块表中就从设备上读取。 在得到了文
// 件系统超级块之后,我们对它先进行检测一番。如果新文件系统已安装在其他地方,或者将要安
// 装到的 i 节点已经安装了文件系统(安装标志已经置位),则都放回该 i 节点,也返回出错码。
 	if (!(sb=read_super(dev))) {
 		iput(dir_i);
 		return -EBUSY;
 	}
 	if (sb->s_imount) {
 		iput(dir_i);
 		return -EBUSY;
 	}
 	if (dir_i->i_mount) {
 		iput(dir_i);
 		return -EPERM;
 	}
// 最后我们设置新文件系统超级块的“被安装到 i 节点”字段指向安装到的目录名的 i 节点,
// 并设置安装位置 i 节点的安装标志和节点已修改标志。然后返回 0(安装成功)。
 	sb->s_imount=dir_i;
	dir_i->i_mount=1;
 	dir_i->i_dirt=1;   /*注意!这里没用 iput(dir_i)*/
 	return 0; 	 /* 这将在 umount 内操作 */
 }

  • 6
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值