0x01 Linux 分区简介

挂载的本质就是针对某一设备, 分析出其文件系统结构, 并根据其文件系统类型调用 linux 中相应的驱动, 处理其的元数据, 将这些信息附加到 linux 的目录树上呈现出来.

原文: Mounting is the attaching of an additional filesystem to the currently accessible filesystem of a computer.

当要使用某个设备时,例如要读取硬盘中的一个格式化好的分区、光盘或软件等设备时,必须先把这些设备对应到某个目录(这个目录可以不为空,但挂载后这个目录下以前的内容将不可用),而这个目录就称为“挂载点(mount point)”,这样才可以读取这些设备,而这些对应的动作就是“挂载”
主分区 vs 扩展分区
硬盘分区表中最多能存储四个分区,但我们实际使用时一般只分为两个分区,一个是主分区(Primary Partion)一个是扩展分区(extended partition),主分区可以马上被使用但不能再分区,扩展分区必须再进行分区后才能使用,也就是说它必须还要进行二次分区, 一般留作未来扩展用的。那么由扩展分区再分下去的是什么呢?它就是逻辑分区(Logical Partion),逻辑分区没有数量上限制, 相当于不同目录取不同名字作”逻辑”上的区分
驱动器标示的含义
对Linux用户来说无论有几个分区,都得分给目录使用,它归根结底就只有一个根目录,一个独立且唯一的文件结构。Linux中每个分区都是用来组成整个文件系统的一部分,因为它采用了一种叫“挂载点”的处理方法,它的整个文件系统中包含了一整套的文件和目录,且将一个分区和一个目录联系起来。这时要载入的一个分区就在linux的存储空间的某个目录下获得。
对于IDE硬盘,驱动器标识符为“hdx1”,其中“hd”表明分区所在设备的类型,这里是指IDE硬盘了。“x”为盘号(a为基本盘,b为基本从属盘,c为辅助主盘,d为辅助从属盘),“1”代表分区,前四个分区用数字1到4表示,它们是主分区或扩展分区,从5开始就是逻辑分区。例,hda3表示为第一个IDE硬盘上的第三个主分区或扩展分区,hdb2表示为第二个IDE硬盘上的第二个主分区或扩展分区。对于SCSI硬盘则标识为“sdx1”,SCSI硬盘是用“sd”来表示分区所在设备的类型的,其余则和IDE硬盘的表示方法一样。
上面可以看到,Linux的分区是不同于其它操作系统分区的,它的分区格式常用的有Ext3和Swap两种,Ext3用于存放系统文件,Swap则作为Linux的交换分区(相当于windows中的虚拟内存文件)。那么现在我们就可以知道Linux至少需要两个专门的分区(Linux Native(本地)和Linux Swap(交换))。由于不能将Linux安装在Dos/Windows分区。一般来说我们将Linux安装一个或多个类型为“Linux Native”的硬盘分区,但是在Linux的每一个分区都必须要指定一个“Mount Point”(挂载点),告诉Linux在启动时,这个目录要给哪个分区使用。对“Swap”分区来说, 一般也定义一个,且它不必要定义载入点。
下面我们先对“Linux Native”和“Linux Swap”有个初步的了解。
SWAP分区是LINUX暂时存储数据的交换分区,它主要是把主内存上暂时不用得数据存起来,在需要的时候再调进内存内,且作为SWAP使用的分区不用指定“Mout Point”(载入点),既然它作为交换分区,我们理所当然应给它指定大小,它至少要等于系统上实际内存的量,一般来说它的大小是内存的一至两倍。另外你也可以创建和使用一个以上的交换分区,最多16个。
Linux Native是存放系统文件的地方,一般用ext3/ext4的分区类型,对Linux来说,有了较大的选择余地,可以把系统文件分几个区来装(必须要说明挂载点),也可以就装在同一个分区中(挂载点是“/”)。
深入linux下磁盘Disk,分区Partition,挂载Mount-冯金伟博客园

为什么要自定义多个分区
a. 在不损失数据的情况下重装系统,比如独立设置/home挂载点,重装系统的时候直接标记回/home,数据不会有任何损失。

b. 针对不同挂载点的特性分配合适的文件系统以合理发挥性能,比如对/var使用reiserfs,对/home使用xfs,对/使用ext4。


c. 针对不同的挂载点开启不同的挂载选项,如是否需要即时同步,是否开启日志,是否启用压缩。


d. 大硬盘搜索范围大,效率低


e. 磁盘配额只能对分区做设定


f. /home、/var、/usr/local 经常是单独分区,因为经常会操作,容易产生碎片

0x02 挂载点目录简介

常见的挂载目录结构

 
深入linux下磁盘Disk,分区Partition,挂载Mount-冯金伟博客园

以上是目录结构
 

 

以下是文件存储结构
在linux正统的文件系统(eg:ext2、ext3)中,一个文件由以下三个部分组成:
1. 目录项:包括文件名和inode节点号。
2. Inode::又称文件索引节点,记录文件的属性,一个文件占用一个inode,同时记录此文件的数据所在的block号码。
3. data block:实际记录文件的内容,若文件太大时,会占用多个block。
 
 
深入linux下磁盘Disk,分区Partition,挂载Mount-冯金伟博客园

深入linux下磁盘Disk,分区Partition,挂载Mount-冯金伟博客园

常见的挂载目录说明
/ 根目录,存放系统命令和用户数据等(如果下面挂载点没有单独的分区,它们都将在根目录的分区中)
/boot boot loader 的静态链接文件,存放与Linux启动相关的程序
/home 用户目录,存放普通用户的数据
/tmp 临时文件
/usr 是Linux系统存放软件的地方,如有可能应将最大空间分给它
/usr/local 自已安装程序安装在此
/var 不断变化的数据,服务器的一些服务、日志放在下面
/opt (Option可选的)附加的应用程序软件包
/bin 基本命令执行文
/dev 设备文件
/etc 主机特定的系统配置
/lib 基本共享库以及内核模块
/media 用于移动介质的挂载点
/mnt 用于临时挂载文件系统或者别的硬件设备(如光驱、软驱)
/proc 系统信息的虚拟目录(2.4 和 2.6 内核),这些信息是在内存中,由系统自己产生的
/root root 用户的目录
/sbin 基本系统命令执行文件
/sys 系统信息的虚拟目录(2.6 内核)
/srv 系统提供的用于 service 的数据
/usr/X1186 X-Windows目录,存放一些X-Windows的配置文件
/usr/include 系统头文件,存储一些C语言的头文件
/usr/src Linux内核源代码,Linux系统所安装的内核源代码都保存在此
/usr/bin 对/bin目录的一些补充
/usr/sbin 对/sbin目录的一些补充
/lost+found 这个目录在大多数情况下都是空的。但是如果你正在工作突然停电,或是没有用正常方式关机,在你重新启动机器的时候,有些文件就会找不到应该存放的地方,对于这些文件,系统将他们放在这个目录下
深入linux下磁盘Disk,分区Partition,挂载Mount-冯金伟博客园

为什么 linux 的分区需要有挂载这个动作呢
因为linux 下一切皆文件!换句说法就是linux操作系统将系统中的一切都作为文件来管理。在windows中我们常见的硬件设备(打印机、网卡、声卡…)、磁盘分区等,在linux中统统都被视作文件,对设备、分区的访问就是读写对应的文件。

0x03 实战分区挂载

临时挂载

$ mount /dev/sda3 /data   ##sda3分区挂载在data目录下
$ umount /data   ##卸载data目录下分区

永久挂载:开机自动挂载

需要修改/etc/fstab

LABEL=/data   /data   ext3   defaults   1   2
修改为:
/dev/sda3     /data      ext3    defaults 1    2

PS:fstab 是文件系统分配表的配置文件,该文件有着严格的语法格式限制,类似 crontab 一样,保存时也会对你的输入格式进行校验,请慎重使用,否则会有意想不到的问题发生。其一共有 6 个字段,空格分隔。

添加硬盘&分区&挂载

参考之前写的文摘《Centos下磁盘分区及挂载

loop device 回环设备

明白 loop mount 之前, 最好先清除什么是 loop device, 有耐心的话可以参见维基百科中的条目, 比较长, 没耐心的话可以直接看我下面的描述, 简洁些.

简单来说, loop device 能够提供将一个档案挂载到某一目录的功能. 这和 bind mount (下文会介绍) 有些类似, 但并不相同. 原始的 mount 只是为了将正常的设备挂载, bind mount 使得可以挂载目录, 而 loop device 使得可以挂载档案.

在 linux 中, loop device 就是指 /dev/loop0, /dev/loop1, /dev/loop2 … 这些设备, 它们是虚假的设备(pseudo device), 不像 /dev/sda 在你的主机里物理存在. loop device 需要你在编译内核的时候将其静态编译或者编译为动态模块, 然后需要使用modprobe加载其模块(这个模块包含了 loop device 的驱动程序以及 losetup 这种提供给用户来操作 loop device 的程序), 这时其驱动程序就回创建 /dev/loop0, /dev/loop1 … 这几个设备文件.

 

注意, 我在说档案的时候, 指的是英文中的 archive, 它和文件 file 是不同的东西, 档案 archive 是一个打包的文件集, 里面一般包含许多文件, 比如 tar, jar, iso 就是常见的档案格式.

用过 dd 的人应该知道, 这个强大的命令可以将整个磁盘或者磁盘分区克隆下来, 放到一个文件里, 一般, 这样的文件我们都以 .img 后缀为其命名并称这样的文件为镜像文件. 我所说的档案也包含这类情况.

5.loop mount

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 

最后我们再来想一想, 是不是所有的档案都可以用这种方式挂载? 显然不是的, 根据mount命令有个 -t 参数来看, 在挂载的时候是需要指定文件系统的类型的(不指定的话mount命令会自动识别), 还记得上面说的挂载的本质吗?

"挂载操作, 实际上是把设备 _device_ 中的**文件系统**附加到 _dir_ 上,". 

不被识别的文件系统是不能被挂载的, 如果你没有加载 ReiserFS 模块, 那么挂载具有 ReiserFS 文件系统的设备时就会报 “unknown file system” 错误. 像上面说的 tar, jar, zip 这样的档案, 它们只是一种打包/压缩格式, 本身就不是一种文件系统格式, 当然是不能被 linux 识别的. 它们虽然可以映射到某一个 loop device, 但并不能被挂载.

但是像 .iso 文件, 它一般包含 iso 9660 文件系统, 都知道这是一种 CD 上采用的文件系统. 还有就是你可以使用 dd, mkfs 命令来创建一个 ext2, ext3 等文件系统的档案. 这样的档案才是可以被挂载的.

loop mount 一直以来是 Unix-like 系统下很有用的特性, 能帮助你当你拿到一个 iso 文件后, 不必将其刻录到 CD/DVD 里就能查看里面的内容. windows 下直到 windows 7 才支持这一特性, 在此之前都需要借助第三方软件如 Daemon Tools 来实现虚拟光驱的功能.

 

6.绑定式挂载 (bind mount)

上面所说的 “挂载” 都是指让你将某个设备挂载到某一目录, 不管这个设备是真实的物理设备, 还是假的 loop 设备, 它都是设备. 而 “绑定式挂载” 能够允许你将已经的存在目录挂载到另一目录. 比如:

 #  mount --bind / /home/username/mnt-point 

这样, 你的 mnt-point 目录下也会有 etc, opt, usr 等目录, 这一过程我们称作 “将根目录绑定到 /home/username/mnt-point 上”, 所以, 你在一处改变目录下的内容的话, 在另一处也能够看到改变.

需要注意的一点是如果根目录树下有某个目录是挂载到另一个磁盘分区的话, 那么它可能不会被绑定到新的目录下. 比如说如果 /usr 和 / 处于不同的磁盘分区(/ 在 sda1, /usr 在 sda2), 那么你可能会发现 /home/username/mnt-point/usr 是空的, 那么这时可以额外挂载一次来使得 /usr 也出现在 /home/username/mnt-point/usr:

 #  mount --bind /usr /home/username/mnt-point/usr 

不过你也可以在一开始就执行:

 #  mount --rbind / /home/username/mnt-point 

关于绑定式挂载,man 2 mount中的描述是 “使一个文件, 或者一个目录树在另一个目录上可见”. 这地方不太理解, 就我所知, 只能将目录绑定到目录, 不能将文件绑定到目录的. 我尝试过将一个普通的文件绑定到目录, 但报错了. 不知道 man 手册里这个说法是什么意思. 我只能这么理解: 目录也是文件, 所以这种说法没错吧….

7.重新挂载 (remount)

借助于绑定式挂载, 可以实现有趣的效果, 比如说, 你可以将 / 绑定到 /, 将 /tmp/test/ 绑定到 /tmp/test/ (运行 mount 命令就能看到效果). 不过… 这么干有个鸟用啊!! 谁这么无聊会去这么干啊!!

这就是 remount 存在的原因, 我们虽然可以通过绑定式挂载耍点小聪明, 将自己绑定到自己上, 但这与没绑定没有任何区别啊; 然而借助 remount, 我们就可以在重新挂载的时候修改挂载的参数.

remount 最常用的情况就是将一个文件系统由只读重新挂载为读写, 或者相反. 比如:

# mount -o remount,rw / 

关于 remount 的详情, 可以看一下 man 手册, 这里就不多介绍了.

0x04 通过 fstab 设置开机挂载的问题

Linux 在启动的时候通过 fstab 中的信息挂载各个分区,一个典型的分区条目就像这样:

/dev/sda3     /data      ext3    defaults 1    2

/dev/sda3 为需要挂载的分区,sda3是 Linux 检测硬盘时按顺序给分区的命名,一般来讲,这个名称并不会变化,但是如果你有多块硬盘,硬盘在电脑中的顺序变化的时候,相同的名称可能代表着不同的硬盘分区。这样的话上面设置的开机自动挂载就会出现找不到分区上面的文件情况
这个时候 UUID 就派上用场了,UUID 全称是 Universally Unique Identifier,也就是说,每个分区有一个唯一的 UUID 值,这样就不会发生分区识别混乱的问题了。
在 fstab 中用 UUID 挂载分区格式如下:

UUID=7cc82613-5be2-4e58-b359-0920613f9509     /data        ext3    defaults   1    2

可以通过下面命令得到分区的UUID

$ ls -l  /dev/disk/by-uuid/

0x05 FAQ

a. 挂载点不一定是一个目录, 可以是文件
b. 一个分区挂载在一个已存在的目录上,这个目录可以不为空,但挂载后这个目录下以前的内容将不可用。对于其他操作系统建立的文件系统的挂载也是这样,卸载后,目录以前的文件都还在,不会有任何丢失
c. 目录只占磁盘里的一个inode,存放文件属性等信息
d. 任何一个分区都必须挂载到某个目录上
e. 目录是逻辑上的。分区是物理上的. 
f. 磁盘Linux分区都必须挂载到目录树中的某个具体的目录上才能进行读写操作
g. 根目录是所有Linux的文件和目录所在的地方,需要挂载上一个磁盘分区
h. 一个分区可以挂在多个目录,但反过来一个目录只能是一个分区的挂载点

参考:

http://cn.linux.vbird.org/linux_basic/0230filesystem_6.php