一、文件结构

在 Linux 系统中,目录、字符设备、块设备、套接字、打印机等都被抽象成了文件,也就是大家常说的“一切皆文件”。

这里引入一个名词叫做:文件系统层次化标准(FHS,Filesystem Hierarchy Standard);

  • Linux 系统中的一切文件都是从“根(/)”目录开始的;
  • 按照文件系统层次化标准(FHS)采用树形结构来存放文件;
  • Linux系统中的文件和目录名称是严格区分大小写的。

Linux 系统中的文件存储结构如图所示。

Linux 系统中常见的目录名称以及相应内容:

二、物理设备

1、物理设备的命名

在Linux系统中,硬件设备也是以文件的形式存储的,既然是文件,就必须有文件名称。

系统内核中的 udev 设备管理器会自动把硬件名称规范起来,目的是让用户通过设备文件的名字可以猜出设备大致的属性以及分区信息等;这对于陌生的设备来说特别方便。

udev设备管理器的服务会一直以守护进程的形式运行并侦听内核发出的信号来管理 /dev 目录下的设备文件。

由于现在的 IDE 设备已经很少见了,所以一般的硬盘设备都会是以“/dev/sd”开头的。另外如果是虚拟机的话,因为虚拟机使用 VirtIO界面,所以可能文件名为/dev/vd开头的。

此系统采用 a~p 来代表 16 块不同的硬盘(默认从 a 开始分配),而且硬盘的分区编号也很有讲究:

  • 主分区扩展分区的编号从 1 开始,到 4 结束;
  • 逻辑分区从编号 5 开始。

至于是 a 还是 b 不是由插槽决定的,而是由系统内核的识别顺序来决定的。

sda3 只能表示是编号为 3 的分区,而不能判断 sda 设备上已经存在了 3 个分区。

  • /dev/目录中保存的应当是硬件设备文件;
  • sd 表示是存储设备;
  • a 表示系统中同类接口中第一个被识别到的设备;
  • 5 表示这个设备是一个逻辑分区。

/dev/sda5”表示的就是“这是系统中第一块被识别到的硬件设备中分区编号为 5 的逻辑分区的设备文件”。

2、硬盘分区概念

  • 硬盘设备是由大量的扇区组成的,每个扇区的容量512 字节。
  • 其中第一个扇区最重要,它里面保存着主引导记录分区表信息。
  • 就第一个扇区来讲,主引导记录需要占用 446 字节,分区表为 64 字节,结束符占用 2 字节;
  • 其中分区表中每记录一个分区信息就需要 16 字节,这样一来最多只有 4 个分区信息可以写到第一个扇区中,这 4 个分区就是 4 个主分区


为了解决分区个数不够的问题,可以将第一个扇区的分区表中 16 字节(原本要写入主分区信息)的空间(称之为扩展分区)拿出来指向另外一个分区。

扩展分区其实并不是一个真正的分区,而更像是一个占用 16 字节分区表空间的指针——一个指向另外一个分区的指针。

这样一来,用户一般会选择使用 3 个主分区加 1 个扩展分区的方法,然后在扩展分区中创建出数个逻辑分区,从而来满足多分区(大于 4 个)的需求。

三、文件系统

用户在硬件存储设备中执行的文件建立、写入、读取、修改、转存与控制等操作都是依靠文件系统来完成的。Linux 系统支持数十种的文件系统,而最常见的文件系统如下所示。

  1. Ext3:是一款日志文件系统,能够在系统异常宕机时避免文件系统资料丢失,并能自动修复数据的不一致与错误。然而,当硬盘容量较大时,所需的修复时间也会很长,而且也不能百分之百地保证资料不会丢失。会把整个磁盘的每个写入动作的细节都预先记录下来,以便在发生异常宕机后能回溯追踪到被中断的部分,然后尝试进行修复。
  2. Ext4:Ext3 的改进版本,作为 RHEL 6 系统中的默认文件管理系统,它支持的存储容量高达 1EB(1EB=1,073,741,824GB),且能够有无限多的子目录。另外,Ext4 文件系统能够批量分配 block 块,从而极大地提高了读写效率。
  3. XFS:是一种高性能的日志文件系统,而且是 RHEL 7 中默认的文件管理系统,它的优势在发生意外宕机后尤其明显,即可以快速地恢复可能被破坏的文件,而且强大的日志功能只用花费极低的计算和存储性能。并且它最大可支持的存储容量为 18EB,这几乎满足了所有需求。

Linux 系统中有一个名为 super block 的“硬盘地图”。Linux 并不是把文件内容直接写入到这个“硬盘地图”里面,而是在里面记录着整个文件系统的信息。Linux 只是把每个文件的权限与属性记录在inode 中,而且每个文件占用一个独立的 inode 表格,该表格的大小默认为 128 字节,里面记录着如下信息:

  • 该文件的访问权限(read、write、execute);
  • 该文件的所有者与所属组(owner、group);
  • 该文件的大小(size);
  • 该文件的创建或内容修改时间(ctime);
  • 该文件的最后一次访问时间(atime);
  • 该文件的修改时间(mtime);
  • 文件的特殊权限(SUID、SGID、SBIT);
  • 该文件的真实数据地址(point)。

而文件的实际内容则保存在 block 块中(大小可以是 1KB、2KB 或 4KB),一个 inode 的默认大小仅为 128B(Ext3),记录一个 block 则消耗 4B。当文件的 inode 被写满后,Linux 系统会自动分配出一个 block 块,专门用于像 inode 那样记录其他 block 块的信息,这样把各个block 块的内容串到一起,就能够让用户读到完整的文件内容了。对于存储文件内容的 block 块,有下面两种常见情况(以 4KB 的 block 大小为例进行说明)。

  • 文件很小(1KB),但依然会占用一个 block,因此会潜在地浪费 3KB。
  • 文件很大(5KB),那么会占用两个 block(5KB-4KB 后剩下的 1KB 也要占用一个 block)。

为了使用户在读取或写入文件时不用关心底层的硬盘结构,Linux 内核中的软件层为用户程序提供了一个 VFS(Virtual File System,虚拟文件系统)接口,这样用户实际上在操作文件时就是统一对这个虚拟文件系统进行操作了。

四、挂载设备

在拿到一块全新的硬盘存储设备后要先分区,然后格式化,最后才能挂载并正常使用。

当用户需要使用硬盘设备或分区中的数据时,需要先将其与一个已存在的目录文件进行关联,而这个关联动作就是“挂载”。

1、mount 命令

mount 命令用于挂载文件系统,格式为“mount 文件系统 挂载目录”。


挂载是在使用硬件设备前所执行的最后一步操作。只需使用 mount 命令把硬盘设备或分区与一个目录文件进行关联,然后就能在这个目录中看到硬件设备中的数据了。

栗子:

要把设备/dev/sdb2 挂载到/backup 目录,只需要在 mount 命令中填写设备与挂载目录参数就行,系统会自动去判断要挂载文件的类型,因此只需要执行下述命令即可:

mount  /dev/sdb2  /backup

但是这样做的话电脑一重启就会回到解放前。如果想让硬件设备和目录永久地进行自动关联,就必须把挂载信息按照指定的填写格式“设备文件 挂载目录 格式类型 权限选项 是否备份 是否自检” 写入到/etc/fstab 文件中。这个文件中包含着挂载所需的诸多信息项目,一旦配置好之后就能一劳永逸了。

如果想将文件系统为 ext4 的硬件设备/dev/sdb2 在开机后自动挂载到 /backup 目录上,并保持默认权限且无需开机自检,就需要在 /etc/fstab 文件中写入下面的信息,这样在系统重启后也会成功挂载。

[root@ubuntu ~]# vim /etc/fstab
#
# /etc/fstab
# Created by anaconda on Wed Feb 4 19:26:23 2020
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
/dev/mapper/rhel-root                     /            xfs         defaults  1  1
UUID=812b1f7c-8b5b-43da-8c06-b9999e0fe48b /boot        xfs         defaults  1  2
/dev/mapper                               /rhel-swap   swap  swap  defaults  0  0
/dev/cdrom                                /media/cdrom iso9660     defaults  0  0
/dev/sdb2                                 /backup      ext4        defaults  0  0

2、umount 命令

umount 命令用于撤销已经挂载的设备文件,格式为“umount [挂载点/设备文件]”。

手动卸载掉/dev/sdb2 设备文件:

umount /dev/sdb2

五、添加设备

这里使用虚拟机来模拟一下向 Linux 系统中添加一块硬盘的流程:

首先需要添加入一块新的硬盘存储设备,然后再进行分区格式化挂载等操作,最后通过检查系统的挂载状态并真实地使用硬盘来验证硬盘设备是否成功添加。


首先打开虚拟机并选择编辑虚拟机配置,然后点击添加:

选择硬盘,点击下一步:

使用推荐的 SCSI 就可以:

选择创建新的虚拟磁盘,点击下一步:

硬盘大小默认 20G 但是这并不是说立马就用完了,所以放心选择,并选择将磁盘拆分为多个文件:

点击完成即可。

可以看到已经创建完成了:

点击确定关闭窗口即可,按照之前我们分析的,现在这块磁盘的名字应该是 /dev/sdb。但在开始使用该硬盘之前还需要进行分区操作,例如从中取出一个 2GB 的分区设备以供后面的操作使用。

六、管理硬盘

1、fdisk 工具

fdisk 命令用于管理磁盘分区,格式为“fdisk [磁盘名称]”,它提供了集添加、删除、转换分区等功能于一身的“一站式分区服务”。


另外 q 是不保存直接退出。

这边虚拟机已经打开了,打开之后果断弃机选择 远程连接


然后就可以远程操作了。

为了避免权限不足首先使用 sudo su 命令切换到管理员。

我们使用 fdisk 命令来尝试管理 /dev/sdb 硬盘设备。在看到提示信息后输入参数 p 来查看硬盘设备内已有的分区信息,其中包括了硬盘的容量大小、扇区个数等信息:

输入参数 n 尝试添加新的分区。系统会要求你是选择继续输入参数 p 来创建主分区,还是输入参数 e 来创建扩展分区。这里输入参数 p 来创建一个主分区:


在确认创建一个主分区后,系统要求您先输入主分区的编号。我们在前文得知,主分区的编号范围是 1~4,因此这里输入默认的 1 就可以了。接下来系统会提示定义起始的扇区位置,这不需要改动,我们敲击回车键保留默认设置即可,系统会自动计算出最靠前的空闲扇区的位置。最后,系统会要求定义分区的结束扇区位置,这其实就是要去定义整个分区的大小是多少。我们不用去计算扇区的个数,只需要输入+2G 即可创建出一个容量为 2GB 的硬盘分区。

再次使用参数 p 来查看硬盘设备中的分区信息。果然就能看到一个名称为/dev/sdb1、起始扇区位置为 2048、结束扇区位置为 4196351 的主分区了。这时候千万不要直接关闭窗口,而应该敲击参数 w 后回车,这样分区信息才是真正的写入成功啦。

在上述步骤执行完毕之后,Linux 系统会自动把这个硬盘主分区抽象成/dev/sdb1 设备文件。我们可以使用 file 命令查看该文件的属性,但是有时候系统并不会自动抽象。我们可以输入 partprobe 命令手动将分区信息同步到内核,而且一般推荐连续两次执行该命令,效果会更好。如果使用这个命令都无法解决问题,那么就重启计算机吧,这个杀手锏百试百灵,一定会有用的。

file /dev/sdb1


如果你没有出现/dev/sdb1: block special (8/17),那就按照上面的方法多试几次吧。

2、mkfs 工具

下面进行格式化,在 Linux 系统中用于格式化操作的命令是mkfs。这条命令很有意思,因为在 Shell 终端中输入 mkfs 名后再敲击两下用于补齐命令的 Tab键,会有如下所示的效果:

这个 mkfs 命令很贴心地把常用的文件系统名称用后缀的方式保存成了多个命令文件,用起来也非常简单—mkfs.文件类型名称。例如要格式分区为 XFS 的文件系统,则命令应为 mkfs.xfs /dev/sdb1

如果你遇到了这种情况:

想想该怎么办呢? 对!就是执行它跟你说的命令啊,apt install xfsprogs,人家新立得就差替你执行了,所以之前很多同学问我一些问题,其中很多都是类似的问题,我就很无语,英语真的不能丢啊,其实学习计算机最最重要的就是算法,其次是英语而不是你学的那些花里胡哨的编程语言!

巧了我电脑里也没有,所以执行了一下:

完成了存储设备的分区和格式化操作,接下来就是要来挂载并使用存储设备了。与之相关的步骤也非常简单:首先是创建一个用于挂载设备的挂载点目录;然后使用 mount 命令将存储设备与挂载点进行关联;最后使用 df -h 命令来查看挂载状态和硬盘使用量信息。

//在根目录新建一个文件夹为newFS
mkdir /newFS
//然后将指定的硬盘挂载上去
mount /dev/sdb1 /newFS/
//查看挂载状态和硬盘使用量信息
df -h

如图:

3、永久挂载

前面在讲解 mount 命令时提到,使用 mount 命令挂载的设备文件会在系统下一次重启的时候失效。如果想让这个设备文件的挂载永久有效,则需要把挂载的信息写入到配置文件中:

vim命令直通车

vim /etc/fstab


完了之后保存退出就行了。

介绍一个用于查看文件数据占用量的 du 命令,其格式为“du [选项][文件]”。简单来说,该命令就是用来查看一个或多个文件占用了多大的硬盘空间。我们还可以使用 du -sh /*命令来查看在 Linux 系统根目录下所有一级目录分别占用的空间大小。

//查看挂载目录的大小
du -sh /newFS/

七、添加交换分区

SWAP(交换)分区是一种通过在硬盘中预先划分一定的空间,然后将把内存中暂时不常用的数据临时存放到硬盘中,以便腾出物理内存空间让更活跃的程序服务来使用的技术,其设计目的是为了解决真实物理内存不足的问题。但由于交换分区毕竟是通过硬盘设备读写数据的,速度肯定要比物理内存慢,所以只有当真实的物理内存耗尽后才会调用交换分区的资源。交换分区的创建过程与前文讲到的挂载并使用存储设备的过程非常相似。在对/dev/sdb 存储设备进行分区操作前,先说一下交换分区的划分建议:在生产环境中,交换分区的大小一般为真实物理内存的 1.5~2 倍,这里取出一个大小为 5GB 的主分区作为交换分区资源。在分区创建完毕后保存并退出即可:

使用 SWAP 分区专用的格式化命令 mkswap,对新建的主分区进行格式化操作:

mkswap /dev/sdb2


使用 swapon 命令把准备好的 SWAP 分区设备正式挂载到系统中。我们可以使用 free -m 命令查看交换分区的大小变化(由 947MB 增加到 6067MB):

free -m
swapon /dev/sdb2
free -m


为了能够让新的交换分区设备在重启后依然生效,需要按照下面的格式将相关信息写入
到配置文件中,并记得保存:

/dev/sdb2 swap swap defaults 0 0