当前位置:首页 > 技术学院 > 技术前线
[导读]很多刚接触Linux的新手都会对"挂载"这个概念感到困惑:为什么Windows插入U盘直接就能打开,Linux要先"挂载"才能用?为什么说"一切皆文件",硬件也要挂载成文件才能访问?到底什么是挂载,它在系统中到底起了什么作用?其实挂载不是Linux独有的概念,但Linux把挂载的设计逻辑用到了极致,它是Linux文件系统体系的核心连接方式,理解了挂载,才能真正理解Linux文件系统的树状结构是怎么搭起来的。

很多刚接触Linux的新手都会对"挂载"这个概念感到困惑:为什么Windows插入U盘直接就能打开,Linux要先"挂载"才能用?为什么说"一切皆文件",硬件也要挂载成文件才能访问?到底什么是挂载,它在系统中到底起了什么作用?其实挂载不是Linux独有的概念,但Linux把挂载的设计逻辑用到了极致,它是Linux文件系统体系的核心连接方式,理解了挂载,才能真正理解Linux文件系统的树状结构是怎么搭起来的。

先搞懂:为什么需要挂载,它解决了什么问题

要理解挂载,首先得回到文件系统的本质:我们存放在硬盘、U盘、SD卡这些存储设备上的数据,需要按照特定的规则组织,才能被操作系统识别和读写,这套组织规则就是文件系统,比如ext4、xfs、NTFS、FAT32都是常见的文件系统格式。

一块新的存储设备,哪怕已经格式化成某个文件系统,它也只是一个独立的存储卷,本身和操作系统的文件目录树没有任何关系。Windows的做法是,给每个存储卷分配一个独立的盘符,比如C盘、D盘、U盘是E盘,用户通过盘符访问不同的存储设备,逻辑简单直接。

但Linux的设计哲学是"一切皆文件",所有文件都要组织成一棵统一的目录树,不管你有多少块硬盘、多少个分区,最终都要整合到这一棵树里,不存在多个盘符的概念。那怎么把一个新的存储卷整合到这棵统一的目录树里呢?这就是‌挂载要做的事情:把一个存储卷的文件系统,关联到统一目录树的某个目录节点上,让用户可以通过这个目录访问这个存储卷的数据。‌

举个最直观的例子:我们买了一台新服务器,通常会给系统盘分一个根分区挂载在/目录下,另外买的数据盘要单独用,我们就把数据盘格式化成ext4,然后把它挂载到/data目录下。这样一来,所有往/data目录写的数据,实际上都会写到数据盘里,而不是系统盘里,根目录下的整个目录树还是完整统一的,用户不需要管这个目录对应哪块硬盘,只要按路径访问就可以了——这就是挂载最核心的作用,把独立的存储文件系统接入到全局目录树中。

反过来,如果没有挂载,我们虽然能识别存储设备,但是没法把它对应到目录树上,用户根本没法按路径访问数据,更没法和已有文件体系整合。所以说挂载本质就是一个"接入"的过程,是操作系统把存储设备的文件系统,连接到用户可见的目录树的桥梁。

挂载的核心逻辑:从设备文件到目录节点的绑定

要理解挂载的完整过程,我们需要拆解一下,执行mount /dev/sdb1 /data这条命令的时候,操作系统到底做了什么,整个过程可以分成四步:

第一步:识别存储设备,找到设备文件

Linux中所有硬件设备都对应/dev目录下的一个设备文件,硬盘通常会被命名为/dev/sda、/dev/sdb,每个分区就是/dev/sda1、/dev/sdb1。/dev/sdb1就是我们要挂载的分区对应的设备文件,操作系统通过这个设备文件就能和硬盘驱动交互,读写分区上的数据。

第二步:解析存储分区的文件系统超级块

要挂载一个文件系统,操作系统首先要识别这个分区是不是已经格式化成了合法的文件系统。每个文件系统都会在分区的固定位置存放一个超级块,超级块里记录了这个文件系统的整体信息:块大小、inode总数、空闲块数量、根inode编号等等。挂载的时候,内核会读取这个超级块,验证文件系统的合法性,如果超级块不对,说明分区没有格式化或者文件系统损坏,就会直接报错挂载失败。

如果超级块验证通过,内核会在内存中缓存这份超级块信息,后续对这个文件系统的所有读写,都会用到这个缓存的信息,不需要每次都从磁盘读取。

第三步:绑定到目标目录,生成挂载点信息

接下来就是挂载最核心的一步:把这个已经识别好的文件系统,绑定到全局目录树的指定目录(也就是我们说的挂载点,这里是/data)。

这里有一个很多新手都会问的问题:如果/data目录原来就有文件,挂载之后原来的文件去哪了?答案很简单:挂载新的文件系统之后,原来/data目录下的内容会被暂时隐藏,直到你把挂载的文件系统卸载之后,原来的内容才会重新显示出来。这是因为挂载点只是目录树中的一个接入锚点,挂载后内核会把所有访问这个目录的请求,转发到新挂载的文件系统上,原来目录的内容依然在原来的文件系统上,只是暂时不可访问而已。

内核会维护一棵全局的挂载树,记录每个目录节点对应哪个已挂载的文件系统,当用户访问某个路径的时候,内核会逐段解析路径,找到路径对应的文件系统,再把请求转发过去,这个过程对用户完全透明。

第四步:返回挂载结果,完成挂载

如果前面三步都没有问题,挂载就完成了,用户现在就可以正常访问/data目录下的文件,读写数据都会落到/dev/sdb1分区上。我们可以用df -h命令看到所有已经挂载的文件系统,能看到/dev/sdb1已经挂载到/data,显示占用了多少空间。

卸载的过程刚好反过来:解除设备文件系统和挂载点的绑定,把内存中的超级块缓存同步回磁盘,清理内核中的挂载信息,原来挂载点的原有内容重新可见,这就是umount命令做的事情。

不只是存储设备:Linux中挂载的多种玩法

很多人以为挂载只能挂载硬盘分区,其实Linux的挂载机制非常灵活,只要是有文件系统的存储介质,甚至是虚拟文件系统,都可以挂载到目录树上,常见的挂载场景远不止数据盘这一种:

1. 根文件系统的挂载:系统启动的第一步

Linux系统启动的时候,第一个挂载就是根文件系统,这是整个系统能跑起来的基础。内核启动完成后,首先要把根分区挂载到/目录,才能找到/sbin/init这样的初始化程序,才能继续启动后续的用户空间进程。如果根文件系统挂载失败,内核直接panic,系统根本启动不了。

根文件系统挂载完成之后,再根据/etc/fstab配置文件,依次挂载其他分区、虚拟文件系统,最终构建出完整的目录树。我们安装系统的时候给分区规划挂载点,本质就是告诉系统,哪个分区要挂载到哪个目录,开机自动挂载。

2. 移动存储的挂载:U盘、移动硬盘的接入

现在的Linux桌面发行版,插入U盘都会自动帮你挂载,一般会挂载到/media/用户名/U盘名称这个路径下,你直接进去访问就可以了,不需要手动执行mount命令,本质还是一样的:把U盘的FAT32或者NTFS文件系统,挂载到目录树的对应位置,才能访问。

如果你用的是无桌面的服务器,插入U盘就需要手动挂载:先找到U盘对应的设备文件/dev/sdb1,然后创建一个目录比如/mnt/usb,再执行mount /dev/sdb1 /mnt/usb,之后就能在/mnt/usb访问U盘数据了。

3. 虚拟文件系统的挂载:proc、sys这些是什么

我们经常看到Linux系统中/proc、/sys这些目录,它们不对应任何硬盘存储,都是虚拟文件系统,也需要挂载才能使用。比如proc文件系统,本质是内核输出系统运行信息的接口,内核把它挂载到/proc目录,用户就能通过读写普通文件的方式,获取进程信息、CPU信息、修改内核参数,比如我们改主机名用的/proc/sys/kernel/hostname,其实就是内核虚拟出来的文件,不存在于任何硬盘上,都是内存中的数据,这也是挂载能实现的,只要把虚拟文件系统挂载到目录节点就可以了。

类似的还有tmpfs,它是基于内存的文件系统,挂载到/tmp目录,所有存在/tmp的文件都存在内存里,读写速度非常快,重启就清空,非常适合放临时文件,这也是挂载的一个典型应用场景。

4. 绑定挂载:把一个目录挂载到另一个位置

Linux还有一种特殊的绑定挂载,就是mount --bind /home/user/data /opt/data,这种挂载不需要新的存储设备,就是把已经存在的一个目录,绑定挂载到另一个位置,这样我们就能从两个路径访问同一个目录的内容,非常灵活。

比如我们要把容器的数据目录移动到新的磁盘,又不想改容器原来的配置,就可以把新磁盘的目录绑定挂载到原来容器的数据路径,不用改配置就能生效,非常方便。

5. ISO镜像的挂载:不需要解压就能访问内容

我们下载了一个ISO的系统镜像,不需要刻录到光盘,也不需要解压,直接就能用挂载命令把它挂载到目录:mount -o loop xxx.iso /mnt/cdrom,然后就能直接访问镜像里面的所有文件,loop设备会把镜像文件当成一个块设备来处理,挂载后就能正常访问,这也是挂载机制灵活性的体现,只要能抽象成文件系统,就能挂载。

常见的挂载相关问题:新手最容易踩的坑

关于挂载,很多新手经常会遇到几个典型的问题,我们也一一拆解清楚:

问题一:为什么有时候卸载提示"设备正忙"?

执行umount的时候经常会报错:target is busy,这是因为当前有进程正在访问这个挂载点的文件,比如某个终端当前工作目录刚好在/data,或者有程序打开了/data里的文件没有关闭,内核不允许卸载正在被访问的文件系统,否则会导致打开这个文件的进程出错,所以就会提示设备正忙。

解决方法也很简单:找到正在访问这个挂载点的进程,把它们关掉,再卸载就可以了,用lsof /data就能看到哪些进程在访问。如果你确实需要强制卸载,可以加-f参数强制卸载,但不推荐,可能会导致数据丢失或者进程异常。

问题二:什么是自动挂载,/etc/fstab是什么?

我们希望服务器重启之后,数据盘依然挂载在原来的位置,不需要每次重启都手动执行mount命令,这就需要把挂载信息写到/etc/fstab配置文件里,系统开机的时候会自动读取这个文件,把里面配置的所有文件系统都挂载好,这就是自动挂载。

/etc/fstab里面每一行就是一个挂载配置,分别是:设备UUID(或者设备路径)、挂载点、文件系统类型、挂载选项、是否dump、是否fsck检查,只要配置正确,开机就会自动挂载。这里推荐用UUID代替设备路径,因为硬盘的设备路径可能会变,但是UUID是每个分区唯一的,不会变,不容易出问题。

问题三:挂载点必须是空目录吗?

前面说过,挂载之后原来目录的内容会被隐藏,所以一般我们都会用空目录做挂载点,避免原来的内容被隐藏导致找不到。但不是说必须是空目录才能挂载,哪怕目录有内容,你依然可以挂载,只是原来的内容暂时访问不到而已,卸载之后就会恢复,不会被删除,很多新手担心挂载会删掉原来目录的文件,其实完全不用担心,只要不格式化,原来的文件一直都在。

问题四:什么是只读挂载,什么是 remount?

有时候我们只需要读数据,不需要修改,就可以用mount -o ro只读挂载,哪怕你不小心想修改文件,内核也会直接报错,防止误修改,非常适合用来恢复数据,比如系统盘损坏了,我们进入急救模式,把系统盘只读挂载出来备份数据,避免误写导致更严重的损坏。

如果你挂载的时候是只读,后来想改成可读写,不需要卸载重新挂载,用mount -o remount,rw /data就能重新挂载,修改挂载选项,非常方便。

挂载的本质:对Linux设计哲学的体现

绕了一圈回来,我们再看挂载这个概念,会发现它的设计非常符合Linux"一切皆文件"的哲学:不管是物理硬盘、U盘、还是内核虚拟出来的信息、内存临时文件、甚至镜像文件,只要抽象成文件系统,就能通过挂载接入到统一的目录树,用户不需要管数据到底存在哪里,是物理存储还是虚拟内存,只要按路径访问文件就可以了,这种设计让整个系统的接口非常统一,扩展能力极强。

很多新手刚接触Linux的时候,觉得挂载这个步骤很麻烦,不如Windows盘符方便,但用久了就会发现这种设计的好处:所有文件都在一棵目录树下,你可以任意把不同的存储挂载到任意位置,灵活调整存储布局,比如你可以把/home单独分一块盘,把/var/log单独挂一块盘,做数据隔离,非常方便,这是盘符做不到的。

结语

挂载本质上不是什么复杂的技术,它就是Linux连接存储和目录树的一个步骤,核心逻辑就是一句话:"把一个独立的文件系统,绑定到全局目录树的某个节点,让用户可以通过路径访问"。理解了这个核心逻辑,你就理解了挂载的本质,不管是挂载数据盘、挂载虚拟文件系统、还是绑定挂载,万变不离其宗。

对于刚接触Linux的开发者来说,搞懂挂载,就搞懂了Linux文件系统的基本结构,后续不管是管理服务器、排查存储问题,都能少踩很多坑。而这个小小的设计,也恰恰体现了Linux的设计哲学:把不同的资源抽象成统一的文件接口,通过挂载整合到一起,简单灵活却无比强大。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除( 邮箱:macysun@21ic.com )。
换一批
延伸阅读

在计算机系统的日常操作中,"挂载"是一个频繁出现却又容易被忽视的概念。无论是在Linux系统中使用mount命令,还是在Windows系统中访问移动硬盘,挂载都在默默发挥着作用。它就像一座桥梁,连接着物理存储设备与操作系...

关键字: 挂载 计算机系统
关闭