20220812 07. Linux 磁盘与文件系统管理

7.1 认识 Linux 文件系统

Linux 最传统的磁盘文件系统 (filesystem) 使用的是 EXT2 这个啦!所以要了解 Linux 的文 件系统就得要由认识 EXT2 开始! 而文件系统是创建在磁盘上面的,因此我们得了解磁盘的 物理组成才行。

7.1.1 磁盘组成与分区的复习

磁盘的物理组成,整颗磁盘的组成主要有:

  • 圆形的盘片(主要记录数据的部分);

  • 机械手臂,与在机械手臂上的磁头(可读写盘片上的数据);

  • 主轴马达,可以转动盘片,让机械手臂的磁头在盘片上读写数据。

数据储存与读取的重点在于盘片,而盘片上的物理组成则为(假设此磁盘为 单碟片)

  • 扇区(Sector)为最小的物理储存单位,且依据磁盘设计的不同,目前主要有 512Bytes 与 4K 两种格式;

  • 将扇区组成一个圆,那就是柱面(Cylinder);

  • 早期的分区主要以柱面为最小分区单位,现在的分区通常使用扇区为最小分区单位(每个扇区都有其号码喔,就好像座位一样);

  • 磁盘分区表主要有两种格式,一种是限制较多的 MBR 分区表,一种是较新且限制较少的 GPT 分区表。

  • MBR 分区表中,第一个扇区最重要,里面有:(1)主要开机区(Master boot record, MBR)及分区表(partition table), 其中 MBR 占有 446 Bytes,而 partition table 则占有 64 Bytes。

  • GPT 分区表除了分区数量扩充较多之外,支持的磁盘容量也可以超过 2TB。

磁盘的文件名

  • /dev/sd[a-p][1-128]:为实体磁盘的磁盘文件名;

  • /dev/vd[a-d][1-128]:为虚拟磁盘的磁盘文件名

以前磁盘分区最小单位经常是柱 面,但 CentOS 7 的分区软件, 已经将最小单位改成扇区了

两种分区表:MBR、GPT

7.1.2 文件系统特性

磁盘分区完毕后还需要进行格式化(format),之后操作系统才能够使用这个文件 系统。 为什么需要进行“格式化”呢?这是因为每种操作系统所设置的文件属性/权限并不相 同, 为了存放这些文件所需的数据,因此就需要将分区进行格式化,以成为操作系统能够利 用的“文件系统格式(filesystem)”。

每种操作系统能够使用的文件系统并不相同。 举例来说,windows 98 以前的微软操作系统主要利用的文件系统是 FAT (或 FAT16),windows 2000 以后的版本 有所谓的 NTFS 文件系统,至于 Linux 的正统文件系统则为 Ext2 (Linux second extended file system, ext2fs)这一个。此外,在默认的情况下,windows 操作系统是不会认识 Linux 的 Ext2 的。

传统的磁盘与文件系统之应用中,一个分区就是只能够被格式化成为一个文件系统,所以我 们可以说一个 filesystem 就是一个 partition。但是由于新技术的利用,例如我们常听到的LVM 与软件磁盘阵列(software raid), 这些技术可以将一个分区格式化为多个文件系统(例如 LVM),也能够将多个分区合成一个文件系统(LVM, RAID)! 所以说,目前我们在格式化 时已经不再说成针对 partition 来格式化了, 通常我们可以称呼一个可被挂载的数据为一个文 件系统而不是一个分区喔!

那么文件系统是如何运行的呢?这与操作系统的文件数据有关。较新的操作系统的文件数据 除了文件实际内容外, 通常含有非常多的属性,例如 Linux 操作系统的文件权限(rwx)与文 件属性(拥有者、群组、时间参数等)。

文件系统通常会将这两部份的数据分别存放在不同 的区块,权限与属性放置到 inode 中,至于实际数据则放置到 data block 区块中。 另外,还 有一个超级区块 (superblock) 会记录整个文件系统的整体信息,包括 inode 与 block 的总 量、使用量、剩余量等。

每个 inode 与 block 都有编号

  • superblock:记录此 filesystem 的整体信息,包括inode/block的总量、使用量、剩余量,以及文件系统的格式与相关信息等;

  • inode:记录文件的属性,一个文件占用一个inode,同时记录此文件的数据所在的 block 号码;

  • block:实际记录文件的内容,若文件太大时,会占用多个 block 。

inode/block 数据存取示意图

这种数据存取的方法我们称为索引式文件系统(indexed allocation)

U盘使用的文件系统一般 为 FAT 格式。FAT 这种格式的文件系统并没有 inode 存在。每个 block 号码都记录在前一个 block 当中

FAT文件系统数据存取示意图

磁盘重组:需要磁盘重组的原因就是文件写入的 block 太过于离散了, 此时文件读取的性能将会变的很差所致。 这个时候可以通过磁盘重组将同一个文件所属的 blocks 汇整在一起,这样数据的读取会比较容易啊! FAT 的文件系统需要三不五 时的磁盘重组一下,Ext2 基本上不太需要常常进行磁盘重组

7.1.3 Linux 的 EXT2 文件系统(inode)

标准的 Linux 文件系统 Ext2 就是使用这种 inode 为基础的文件系统

Ext2 文件系统在格式化的时候基本上是区分为多个区块群组 (block group) 的,每个区块群组都有独立的 inode/block/superblock 系统

ext2文件系统示意图

在整体的规划当中,文件系统最前面有一个开机扇区(boot sector),这个开机扇区可以安 装开机管理程序

每一个区块群组(block group)的六个主要内容说明如下

data block (数据区块)

data block 是用来放置文件内容数据地方,在 Ext2 文件系统中所支持的 block 大小有 1K, 2K 及 4K 三种而已

由于 block 大小的差异,会导致该文件系统能够支持的最大磁 盘容量与最大单一文件大小并不相同

block 基本限制如下:

  • 原则上,block 的大小与数量在格式化完就不能够再改变了(除非重新格式化);

  • 每个 block 内最多只能够放置一个文件的数据;

  • 承上,如果文件大于 block 的大小,则一个文件会占用多个 block 数量;

  • 承上,若文件小于 block ,则该 block 的剩余容量就不能够再被使用了(磁盘空间会浪费)

在您进行文件系统的格式化之前,请先想好该文件系统预计使用的情况。现在的磁盘容量都太大了!所以,大概大家都只会选择 4K 的 block 大小吧

inode table (inode 表格)

inode 的内容在记录文件的属性以及该文件实 际数据是放置在哪几号 block 内! 基本上,inode 记录的文件数据至少有下面这些:

  • 该文件的存取模式(read/write/excute);

  • 该文件的拥有者与群组(owner/group);

  • 该文件的容量;

  • 该文件创建或状态改变的时间(ctime);

  • 最近一次的读取时间(atime);

  • 最近修改的时间(mtime);

  • 定义文件特性的旗标(flag),如 SetUID...;

  • 该文件真正内容的指向 (pointer);

inode 的数量与大小也是在格式化时就已经固定了,除此之外 inode 还有些什么特色呢?

  • 每个 inode 大小均固定为 128 Bytes (新的 ext4 与 xfs 可设置到 256 Bytes);

  • 每个文件都仅会占用一个 inode 而已;

  • 承上,因此文件系统能够创建的文件数量与 inode 的数量有关;

  • 系统读取文件时需要先找到 inode,并分析 inode 所记录的权限与使用者是否符合,若符合才能够开始实际读取 block 的内容。

inode 的结构

inode 结构示意图

这样子 inode 能够指定多少个 block 呢?

  • 12 个直接指向: 12*1K=12K 由于是直接指向,所以总共可记录 12 笔记录,因此总额大小为如上所示;

  • 间接: 256*1K=256K 每笔 block 号码的记录会花去 4Bytes,因此 1K 的大小能够记录256 笔记录,因此一个间接可以记录的文件大小如上;

  • 双间接: 2562561K=2562K 第一层 block 会指定 256 个第二层,每个第二层可以指定 256 个号码,因此总额大小如上;

  • 三间接: 256256256*1K=2563K 第一层 block 会指定 256 个第二层,每个第二层可以指定 256 个第三层,每个第三层可以指定 256 个号码,因此总额大小如上;

  • 总额:将直接、间接、双间接、三间接加总,得到 12 + 256 + 256256 + 256256*256(K) = 16GB

当文件系统将 block 格式化为 1K 大小时,能够容纳的最大文件为 16GB

Superblock (超级区块)

Superblock 是记录整个 filesystem 相关信息的地方。他记录的信息主要有:

  • block 与 inode 的总量;

  • 未使用与已使用的 inode / block 数量;

  • block 与 inode 的大小 (block 为 1, 2, 4K,inode 为 128Bytes 或 256Bytes);

  • filesystem 的挂载时间、最近一次写入数据的时间、最近一次检验磁盘 (fsck) 的时间等文件系统的相关信息;

  • 一个 valid bit 数值,若此文件系统已被挂载,则 valid bit 为 0 ,若未被挂载,则 valid bit 为 1 。

一般来说, superblock 的大小为 1024Bytes

事实上除了第一个 block group 内会含有 superblock 之外,后续的 block group 不一定含有 superblock , 而若含有 superblock 则该 superblock 主要是做为第一个 block group 内 superblock 的备份咯,这样可以进行 superblock 的救援 呢!

Filesystem Description (文件系统描述说明)

这个区段可以描述每个 block group 的开始与结束的 block 号码,以及说明每个区段 (superblock, bitmap, inodemap, data block) 分别介于哪一个 block 号码之间。这部份也能 够用 dumpe2fs 来观察的。

block bitmap (区块对照表)

新增文件时选择“空 的 block ”来记录新文件的数据,从 block bitmap 当中可以知道哪些 block 是空的

删除某些文件时,在 block bitmap 当中相对应到该 block 号码的标志就得要修改成为“未使用中”

inode bitmap (inode 对照表)

与 block bitmap 是类似的功能,只是 block bitmap 记录的是使用与未使用的 block 号码, 至于 inode bitmap 则是记录使用与未使用的 inode 号码

dumpe2fs: 查询 Ext 家族 superblock 信息的指令

每个区段与 superblock 的信息都可以使用 dumpe2fs 这个指令来查询

dumpe2fs [-bh] 设备文件名 

选项与参数: 
-b :列出保留为坏轨的部分
-h :仅列出 superblock 的数据,不会列出其他的区段内容!
dumpe2fs /dev/vda5

7.1.4 与目录树的关系

在 Linux 系统下,每个文件(不管是一般文件还是目录文件)都 会占用一个 inode , 且可依据文件内容的大小来分配多个 block 给该文件使用。

目录的内容在记录文件名, 一般文件才是实际记录数据内容的地方

目录

在 Linux 下的文件系统创建一个目录时,文件系统会分配一个 inode 与至少一块 block 给该目录。其中,inode 记录该目录的相关权限与属性,并可记录分配到的那块 block 号码; 而 block 则是记录在这个目录下的文件名与该文件名占用的 inode 号码数据

如果想要实际观察 root 主文件夹内的文件所占用的 inode 号码时,可以使用 ls -i 这个选项来 处理

由于根目录使用的 block 大小为 4K ,因此每个目录的大小几乎都是 4K 的倍数

在目录下面的文 件数如果太多而导致一个 block 无法容纳的下所有的文件名与 inode 对照表时,Linux 会给予 该目录多一个 block 来继续记录相关的数据

文件

在 Linux 下的 ext2 创建一个一般文件时, ext2 会分配一个 inode 与相对于该文件大小 的 block 数量给该文件

例如:假设我的一个 block 为 4 KBytes ,而我要创建一个 100 KBytes 的文件,那么 linux 将分配一个 inode 与 25 个 block 来储存该文件! 但同时请注意, 由于 inode 仅有 12 个直接指向,因此还要多一个 block 来作为区块号码的记录喔

目录树读取

inode 本身并不记录文件名,文件名的记录 是在目录的 block 当中

新增/删除/ 更名文件名与目录的 w 权限有关

因为文件名是记录在目录的 block 当中, 因此当我们要读取某个文件时,就务必会经过目录的 inode 与 block ,然后才能够找到那个待读取 文件的 inode 号码, 最终才会读到正确的文件的 block 内的数据

由于目录树是由根目录开始读起,因此系统通过挂载的信息可以找到挂载点的 inode 号码, 此时就能够得到根目录的 inode 内容,并依据该 inode 读取根目录的 block 内的文件名数据, 再一层一层的往下读到正确的文件名。

举例:读取 /etc/passwd 这个文件

ll -di / /etc /etc/passwd 
128 dr-xr-xr-x. 17 root root 4096 May 4 17:56 / 
33595521 drwxr-xr-x. 131 root root 8192 Jun 17 00:20 
/etc 36628004 -rw-r--r--. 1 root root 2092 Jun 17 00:20 /etc/passwd

该文件的读取流程为 (假设读取者身份为 dmtsai 这个一般身份使用者):

  1. / 的 inode: 通过挂载点的信息找到 inode 号码为 128 的根目录 inode,且 inode 规范的权限让我们可以读取该 block 的内容(有 r 与 x) ;

  2. / 的 block: 经过上个步骤取得 block 的号码,并找到该内容有 etc/ 目录的 inode 号码(33595521);

  3. etc/ 的 inode: 读取 33595521 号 inode 得知 dmtsai 具有 r 与 x 的权限,因此可以读取 etc/ 的 block 内容;

  4. etc/ 的 block: 经过上个步骤取得 block 号码,并找到该内容有 passwd 文件的 inode 号码 (36628004);

  5. passwd 的 inode: 读取 36628004 号 inode 得知 dmtsai 具有 r 的权限,因此可以读取 passwd 的 block 内容;

  6. passwd 的 block: 最后将该 block 内容的数据读出来。

filesystem 大小与磁盘读取性能

关于文件系统的使用效率上,当你的一个文件系统规划的很大时,例如 100GB 这么大 时, 由于磁盘上面的数据总是来来去去的,所以,整个文件系统上面的文件通常无法连续写 在一起(block 号码不会连续的意思), 而是填入式的将数据填入没有被使用的 block 当中。 如果文件写入的 block 真的分的很散, 此时就会有所谓的文件数据离散的问题发生了

如果文件真的太过离散,确实还是会发生读取效率低落的问题。 因 为磁头还是得要在整个文件系统中来来去去的频繁读取

可以将整个 filesystme 内的数据全部复制出来,将该 filesystem 重新格式化, 再将数据给他复制回去即 可解决这个问题。

此外,如果 filesystem 真的太大了,那么当一个文件分别记录在这个文件系统的最前面与最 后面的 block 号码中, 此时会造成磁盘的机械手臂移动幅度过大,也会造成数据读取性能的 低落。而且磁头在搜寻整个 filesystem 时, 也会花费比较多的时间去搜寻!因此, partition 的规划并不是越大越好, 而是真的要针对您的主机用途来进行规划才行

7.1.5 EXT2/EXT3/EXT4 文件的存取与日志式文件系统的功能

新增一个文件,此时文件系统的行为是:

  1. 先确定使用者对于欲新增文件的目录是否具有 w 与 x 的权限,若有的话才能新增;

  2. 根据 inode bitmap 找到没有使用的 inode 号码,并将新文件的权限/属性写入;

  3. 根据 block bitmap 找到没有使用中的 block 号码,并将实际的数据写入 block 中,且更新 inode 的 block 指向数据;

  4. 将刚刚写入的 inode 与 block 数据同步更新 inode bitmap 与 block bitmap,并更新 superblock 的内容。

将 inode table 与 data block 称为数据存放区域,至于其他例如 superblock、 block bitmap 与 inode bitmap 等区段就被称为 metadata (中介数据) 啰,因为 superblock, inode bitmap 及 block bitmap 的数据是经常变动的,每次新增、移除、编辑时都可能会影响 到这三个部分的数据,因此才被称为中介数据的啦。

数据的不一致 (Inconsistent) 状态

文件在写入文件系统时,因为不知名原因导致系统中断(例如突然的停电啊、 系统核 心发生错误啊~等等的怪事发生时),所以写入的数据仅有 inode table 及 data block 而已, 最后一个同步更新中介数据的步骤并没有做完,此时就会发生 metadata 的内容与实际数据存 放区产生不一致 (Inconsistent) 的情况

在早期的 Ext2 文件系统中,如果发生这个问题, 那么系统在 重新开机的时候,就会借由 Superblock 当中记录的 valid bit (是否有挂载) 与 filesystem state (clean 与否) 等状态来判断是否强制进行数据一致性的检查!若有需要检查时则以 e2fsck 这支程序来进行的。

这样的检查真的是很费时

也就造成后来所谓日志式文件系统的兴起

日志式文件系统 (Journaling filesystem)

在 我们的 filesystem 当中规划出一个区块,该区块专门在记录写入或修订文件时的步骤

  1. 预备:当系统要写入一个文件时,会先在日志记录区块中纪录某个文件准备要写入的信息;

  2. 实际写入:开始写入文件的权限与数据;开始更新 metadata 的数据;

  3. 结束:完成数据与 metadata 的更新后,在日志记录区块当中完成该文件的纪录。

在这样的程序当中,万一数据的纪录过程当中发生了问题,那么我们的系统只要去检查日志 记录区块, 就可以知道哪个文件发生了问题,针对该问题来做一致性的检查即可,而不必针 对整块 filesystem 去检查, 这样就可以达到快速修复 filesystem 的能力了!这就是日志式文 件最基础的功能

ext2 可达到这样的功能吗?当然可以啊! 就通过 ext3/ext4 即可! ext3/ext4 是 ext2 的升级版本,并且可向下相容 ext2 版本呢

dumpe2fs 输出的讯息,可以发现 superblock 里 面含有下面这样的信息:

Journal inode: 8 
Journal backup: inode blocks 
Journal features: (none) 
Journal size: 32M 
Journal length: 8192 
Journal sequence: 0x00000001

通过 inode 8 号记录 journal 区块的 block 指向,而且具有 32MB 的容量在处理日 志呢

7.1.6 Linux 文件系统的运行

所有的数据 都得要载入到内存后 CPU 才能够对该数据进行处理

想一想,如果你常常编辑一个好大的文 件, 在编辑的过程中又频繁的要系统来写入到磁盘中,由于磁盘写入的速度要比内存慢很 多, 因此你会常常耗在等待磁盘的写入/读取上。

为了解决这个效率的问题,因此我们的 Linux 使用的方式是通过一个称为非同步处理 (asynchronously) 的方式

当系统载入一个文件到内存后,如果该文件没有被更动过,则在内存区段的文件数据会被设 置为干净(clean)的。 但如果内存中的文件数据被更改过了(例如你用 nano 去编辑过这个 文件),此时该内存中的数据会被设置为脏的 (Dirty)。此时所有的动作都还在内存中执 行,并没有写入到磁盘中! 系统会不定时的将内存中设置为“Dirty”的数据写回磁盘,以保持 磁盘与内存数据的一致性。

  • 系统会将常用的文件数据放置到内存的缓冲区,以加速文件系统的读/写;

  • 承上,因此 Linux 的实体内存最后都会被用光!这是正常的情况!可加速系统性能;

  • 你可以手动使用 sync 来强迫内存中设置为 Dirty 的文件回写到磁盘中;

  • 若正常关机时,关机指令会主动调用 sync 来将内存的数据回写入磁盘内;

  • 但若不正常关机(如跳电、死机或其他不明原因),由于数据尚未回写到磁盘内, 因此重新开机后可能会花很多时间在进行磁盘检验,甚至可能导致文件系统的损毁(非磁盘损毁)。

7.1.7 挂载点的意义 (mount point)

每个 filesystem 都有独立的 inode / block / superblock 等信息,这个文件系统要能够链接到目 录树才能被我们使用。 将文件系统与目录树结合的动作我们称为“挂载”。

挂载点一定是目录,该目录为进入该文件系统的入口。 因此并不是你有任何文件系统都能使用,必须要“挂载”到目录树的某个目录后,才能够使用该 文件系统的

举例来说,如果你是依据鸟哥的方法安装你的 CentOS 7.x 的话, 那么应该会有三个挂载点 才是,分别是 /, /boot, /home 三个 (鸟哥的系统上对应的设备文件名为 LVM, LVM, /dev/vda2)

ls -lid / /boot /home 
128 dr-xr-xr-x. 17 root root 4096 May 4 17:56 / 
128 dr-xr-xr-x. 4 root root 4096 May 4 17:59 /boot 
128 drwxr-xr-x. 5 root root 41 Jun 17 00:20 /home

由于 XFS filesystem 最顶层的目录之 inode 一般为 128 号,因此可以发现 /, /boot, /home 为三个不同的 filesystem

在第六章一开始的路径中曾经提到根目录下的 . 与 .. 是相 同的东西, 因为权限是一模一样嘛!如果使用文件系统的观点来看,同一个 filesystem 的某 个 inode 只会对应到一个文件内容而已(因为一个文件占用一个 inode 之故), 因此我们可 以通过判断 inode 号码来确认不同文件名是否为相同的文件

ls -ild / /. /.. 
128 dr-xr-xr-x. 17 root root 4096 May 4 17:56 / 
128 dr-xr-xr-x. 17 root root 4096 May 4 17:56 /. 
128 dr-xr-xr-x. 17 root root 4096 May 4 17:56 /..

由于挂载点均为 / ,因此三个文件 (/, /., /..) 均在同一个 filesystem 内,而这 三个文件的 inode 号码均为 128 号,因此这三个文件名都指向同一个 inode 号码,当然这三 个文件的内容也就完全一模一样了! 也就是说,根目录的上层 (/..) 就是他自己

7.1.8 其他 Linux 支持的文件系统与 VFS

Linux 常见的支持文件系统有:

  • 传统文件系统:ext2 / minix / MS-DOS / FAT (用 vfat 模块) / iso9660 (光盘)等等;

  • 日志式文件系统: ext3 /ext4 / ReiserFS / Windows' NTFS / IBM's JFS / SGI's XFS / ZFS

  • 网络文件系统: NFS / SMBFS

查看 Linux 支持的文件系统有哪些

ls -l /lib/modules/$(uname -r)/kernel/fs

系统目前已载入到内存中支持的文件系统则有:

cat /proc/filesystems

Linux VFS (Virtual Filesystem Switch)

Linux 的核心又是如何管理这些认 识的文件系统呢? 其实,整个 Linux 的系统都是通过一个名为 Virtual Filesystem Switch 的核 心功能去读取 filesystem 的。 也就是说,整个 Linux 认识的 filesystem 其实都是 VFS 在进行 管理,我们使用者并不需要知道每个 partition 上头的 filesystem 是什么~ VFS 会主动的帮我 们做好读取的动作呢~

VFS 文件系统的示意图

7.1.9 XFS 文件系统简介

CentOS 7 开始,默认的文件系统已经由原本的 EXT4 变成了 XFS 文件系统了

EXT 家族当前较伤脑筋的地方:支持度最广,但格式化超慢

Ext 文件系统家族对于文件格式化的处理方面,采用的是预先规划出所有的 inode/block/meta data 等数据,未来系统可以直接取用, 不需要再进行动态配置的作法

对鸟哥来说, 性能并不是主要改变文件系统的考虑!对于文 件系统的复原速度、创建速度,可能才是鸟哥改换成 xfs 的思考点。

XFS 文件系统的配置

xfs 就是被开发来用于大容量磁盘以及高性能文件系统之用

几乎所有 Ext4 文件系统有的功能, xfs 都可以具备

xfs 文件系统在数据的分佈上,主要规划为三个部份,一个数据区 (data section)、一个文 件系统活动登录区 (log section)以及一个实时运行区 (realtime section)。

XFS 文件系统的描述数据观察

使用 xfs_info 去观察

xfs_info 挂载点

df
df -T /boot
xfs_info /dev/vda2

7.2 文件系统的简单操作

7.2.1 磁盘与目录的容量

磁盘的整体数据是在 superblock 区块中,但是每个各别文件的容量则在 inode 当中记载的。

  • df:列出文件系统的整体磁盘使用量;

  • du:评估文件系统的磁盘使用量(常用在推估目录所占容量)

df

df [-ahikHTm] [目录或文件名] 

选项与参数: 
-a :列出所有的文件系统,包括系统特有的 /proc 等文件系统; 
-k :以 KBytes 的容量显示各文件系统; 
-m :以 MBytes 的容量显示各文件系统; 
-h :以人们较易阅读的 GBytes, MBytes, KBytes 等格式自行显示; 
-H :以 M=1000K 取代 M=1024K 的进位方式; 
-T :连同该 partition 的 filesystem 名称 (例如 xfs) 也列出; 
-i :不用磁盘容量,而以 inode 的数量来显示
# 范例一:将系统内所有的 filesystem 列出来!
df

# 范例二:将容量结果以易读的容量格式显示出来
df -h

# 范例三:将系统内的所有特殊文件格式及名称都列出来
df -aT
# 系统里面其实还有很多特殊的文件系统存在的。那些比较特殊的文件系统几乎都是在内存当中,例如 /proc 这个挂载点。因此,这些特殊的文件系统都不会占据磁盘空间

# 范例四:将 /etc 下面的可用的磁盘容量以易读的容量格式显示
df -h /etc
# 在 df 后面加上目录或者是文件时, df 会自动的分析该目录或文件所在的 partition ,并将该 partition 的容量显示出来, 所以,您就可以知道某个目录下面还有多少容量可以使用了


# 范例五:将目前各个 partition 当中可用的 inode 数量列出
df -ih

在 Linux 下面如果 df 没有加任何选项,那么默认会将系统内所有的(不含特殊内存内的文件系统与 swap) 都以 1 KBytes 的容量来列出来

  • Filesystem:代表该文件系统是在哪个 partition ,所以列出设备名称;

  • 1k-blocks:说明下面的数字单位是 1KB 呦!可利用 -h 或 -m 来改变容量;

  • Used:顾名思义,就是使用掉的磁盘空间啦!

  • Available:也就是剩下的磁盘空间大小;

  • Use%:就是磁盘的使用率啦!如果使用率高达 90% 以上时, 最好需要注意一下了,免得容量不足造成系统问题喔!(例如最容易被灌爆的 /var/spool/mail 这个放置邮件的磁盘)

  • Mounted on:就是磁盘挂载的目录所在啦!(挂载点啦!)

由于 df 主要读取的数据几乎都是针对一整个文件系统,因此读取的范围主要是在 Superblock 内的信息, 所以这个指令显示结果的速度非常的快速

在显示的结果中你需要特别留意的是 那个根目录的剩余容量! 因为我们所有的数据都是由根目录衍生出来的,因此当根目录的剩 余容量剩下 0 时,那你的 Linux 可能就问题很大了

如果使用 -a 这个参数时,系统会出现 /proc 这个挂载点,但是里面的东 西都是 0 ,不要紧张! /proc 的东西都是 Linux 系统所需要载入的系统数据,而且是挂载 在“内存当中”的, 所以当然没有占任何的磁盘空间啰

至于那个 /dev/shm/ 目录,其实是利用内存虚拟出来的磁盘空间,通常是总实体内存的一半! 由于是通过内存仿真出来的磁盘,因此你在这个目录下面创建任何数据文件时,存取速度是 非常快速的!(在内存内工作) 不过,也由于他是内存仿真出来的,因此这个文件系统的大 小在每部主机上都不一样,而且创建的东西在下次开机时就消失了! 因为是在内存中

du

du [-ahskm] 文件或目录名称 

选项与参数: 
-a :列出所有的文件与目录容量,因为默认仅统计目录下面的文件量而已。 
-h :以人们较易读的容量格式 (G/M) 显示; 
-s :列出总量而已,而不列出每个各别的目录占用容量; 
-S :不包括子目录下的总计,与 -s 有点差别。 
-k :以 KBytes 列出容量显示; 
-m :以 MBytes 列出容量显示;
# 范例一:列出目前目录下的所有文件大小
du
# 直接输入 du 没有加任何选项时,则 du 会分析“目前所在目录” 的文件与目录所占用的磁盘空间。但是,实际显示时,仅会显示目录容量(不含文件), 因此 . 目录有很多文件没有被列出来,所以全部的目录相加不会等于 . 的容量喔! 此外,输出的数值数据为 1K 大小的容量单位。

# 范例二:同范例一,但是将文件的容量也列出来
du -a

# 范例三:检查根目录下面每个目录所占用的容量
du -sm /*
#  这是个很常被使用的功能~利用万用字符 * 来代表每个目录,如果想要检查某个目录下,  哪个次目录占用最大的容量,可以用这个方法找出来。值得注意的是,如果刚刚安装好 Linux 时,  那么整个系统容量最大的应该是 /usr 。而 /proc 虽然有列出容量,但是那个容量是在内存中,  不占磁盘空间。至于 /proc 里头会列出一堆“No such file or directory” 的错误, 因为是内存内的程序,程序执行结束就会消失,因此会有些目录找不到,是正确的!

与 df 不一样的是,du 这个指令其实会直接到文件系统内去搜寻所有的文件数据, 所以上述 第三个范例指令的运行会执行一小段时间

如果你只 想要知道该目录占了多少容量的话,使用 -s 就可以啦! 至于 -S 这个选项部分,由于 du 默认会将所有文件的大小均列出,因此假设你在 /etc 下面使 用 du 时, 所有的文件大小,包括 /etc 下面的次目录容量也会被计算一次。然后最终的容量 (/etc) 也会加总一次, 因此很多朋友都会误会 du 分析的结果不太对劲。所以啰,如果想要 列出某目录下的全部数据, 或许也可以加上 -S 的选项,减少次目录的加总喔!

7.2.2 实体链接与符号链接: ln

在 Linux 下面的链接文件有两种,一种是类似 Windows 的捷径功能的文件,可以让你快速的 链接到目标文件(或目录); 另一种则是通过文件系统的 inode 链接来产生新文件名,而不 是产生新文件!这种称为实体链接 (hard link)

  • 每个文件都会占用一个 inode ,文件内容由 inode 的记录来指向;

  • 想要读取该文件,必须要经过目录记录的文件名来指向到正确的 inode 号码才能读取。

文件名只与目录有关,但是文件内容则与 inode 有关

有没有 可能有多个文件名对应到同一个 inode 号码呢?有的!那就是 hard link 的由来

hard link 只是在某个目录下新增一笔文件名链接到某 inode 号码的关连记录而已

# 创建实体链接
ln /etc/crontab .
# 查看文件所在的inode,链接数2,两个inode相同
ll -i /etc/crontab crontab

实体链接的文件读 取示意图

实体链接的文件读取示意图

一般来说,使用 hard link 设置链接文件时,磁盘的空间与 inode 的数目都不会改变

hard link 是有限制的:

  • 不能跨 Filesystem;

  • 不能 link 目录。

Symbolic link 就是在创建一个 独立的文件,而这个文件会让数据的读取指向他 link 的那个文件的文件名!由于只是利用文 件来做为指向的动作, 所以,当来源文件被删除之后,symbolic link 的文件会“开不了”, 会 一直说“无法打开某文件!”。实际上就是找不到原始“文件名”而已

# 创建符号链接
ln -s /etc/crontab crontab2
# 查看文件所在的inode,两者inode不同
ll -i /etc/crontab crontab2

crontab2 大小是12,因为文件名“/etc/crontab”总共有 12 个英 文,每个英文占用 1 个 Bytes

符号链接的文件读 取示意图

符号链接的文件读取示意图

由 Symbolic link 所创建的文件为一个独立的新的文件,所以会占用掉 inode 与 block 喔

ln [-sf] 来源文件 目标文件 

选项与参数: 
-s :如果不加任何参数就进行链接,那就是hard link,至于 -s 就是symbolic link 
-f :如果 目标文件 存在时,就主动的将目标文件直接移除后再创建!
# 范例一:将 /etc/passwd 复制到 /tmp 下面,并且观察 inode 与 block
cd /tmp
cp -a /etc/passwd .
du -sb ; df -i .

# 范例二:将 /tmp/passwd 制作 hard link 成为 passwd-hd 文件,并观察文件与容量
ln passwd passwd-hd
du -sb ; df -i .
# 整个 inode 与 block 的容量并没有改变

ls -il passwd*
# 指向同一个 inode,第二栏的链接数也会增加


# 范例三:将 /tmp/passwd 创建一个符号链接
ln -s passwd passwd-so
ls -li passwd*
# 指向的 inode 不同
du -sb ; df -i .
# 整个 inode 与 block 的容量有改变


# 范例四:删除原始文件 passwd ,其他两个文件是否能够打开?
rm passwd
cat passwd-hd
cat passwd-so
# 符号链接无法打开,ll 符号链接文件名的部分就会有特殊的颜色显示

使用 ln 如果不加任何参数的话,那么就是 Hard Link

当我们以 hard link 进行“文件的链接”时,可以发现,在 ls -l 所 显示的第二字段会增加一

如果创建目录时,他默认的 link 数量会是多少?

当我们创建一个新目录名称为 /tmp/testing 时,基本上会有三个东西,那就是:

  • /tmp/testing

  • /tmp/testing/.

  • /tmp/testing/..

其中 /tmp/testing 与 /tmp/testing/. 其实是一样的

所以说,当我们创建一个新的目录时, “新的目录的 link 数为 2 ,而上层 目录的 link 数则会增加 1 ”

ls -ld /tmp
mkdir /tmp/testing1
ls -ld /tmp
ls -ld /tmp/testing1

上层目录 /tmp 的 link 数量 +1 ,新目录 /tmp/testing 则为 2

7.3 磁盘的分区、格式化、检验与挂载

如果我们想要在系统里面新增一颗磁盘时,应该有哪些动作需要做的呢:

  1. 对磁盘进行分区,以创建可用的 partition ;

  2. 对该 partition 进行格式化 (format),以创建系统可用的 filesystem;

  3. 若想要仔细一点,则可对刚刚创建好的 filesystem 进行检验;

  4. 在 Linux 系统上,需要创建挂载点 (亦即是目录),并将他挂载上来;

7.3.1 观察磁盘分区状态

lsblk 列出系统上的所有磁盘列表

lsblk 可以看成“ list block device ”的缩写,就是列出所有储存设备的意思

lsblk [-dfimpt] [device] 

选项与参数: 
-d :仅列出磁盘本身,并不会列出该磁盘的分区数据 
-f :同时列出该磁盘内的文件系统名称 
-i :使用 ASCII 的线段输出,不要使用复杂的编码 (在某些环境下很有用) 
-m :同时输出该设备在 /dev 下面的权限数据 (rwx 的数据) 
-p :列出该设备的完整文件名!而不是仅列出最后的名字而已。 
-t :列出该磁盘设备的详细数据,包括磁盘伫列机制、预读写的数据量大小等
# 范例一:列出本系统下的所有磁盘与磁盘内的分区信息
lsblk

从范例一我们来谈谈默认输出的信息有哪些。

  • NAME:就是设备的文件名啰!会省略 /dev 等前导目录!

  • MAJ:MIN:其实核心认识的设备都是通过这两个代码来熟悉的!分别是主要:次要设备代码!

  • RM:是否为可卸载设备 (removable device),如光盘、USB 磁盘等等

  • SIZE:当然就是容量啰!

  • RO:是否为只读设备的意思

  • TYPE:是磁盘 (disk)、分区 (partition) 还是只读存储器 (rom) 等输出

  • MOUTPOINT:就是前一章谈到的挂载点!

# 范例二:仅列出 /dev/vda 设备内的所有数据的完整文件名
lsblk -ip /dev/vda

blkid 列出设备的 UUID 等参数

UUID 是全域单一识别码 (universally unique identifier),Linux 会将系统内所有的设备都给予一个独一无二的识别 码, 这个识别码就可以拿来作为挂载或者是使用这个设备/文件系统之用

blkid

每一行代表一个文件系统,主要列出设备名称、UUID 名称以及文件系统的类型 (TYPE)

parted 列出磁盘的分区表类型与分区信息

# 范例一:列出 /dev/vda 磁盘的相关数据
parted /dev/vda print

分区表的格式查看 Partition Table , msdos 表示 MBR ,gpt 表示 GPT

7.3.2 磁盘分区: gdisk/fdisk

MBR 分区表请使用 fdisk 分区, GPT 分区 表请使用 gdisk 分区

fdisk 跟 gdisk 使用的方式几乎一样!只是一个使用 ? 作为指令提示数据,一个使用 m 作为提示这样而已。 此外,fdisk 有时会使用柱面 (cylinder) 作为分区的最小单位,与 gdisk 默认使用 sector 不太一样!

7.3.3 磁盘格式化(创建文件系统)

make filesystem, mkfs

“格式化”其实应该称为“创建文件系统 (make filesystem)”才对

mkfs.xfs 指令创建 xfs 文件系统

mkfs.ext4 指令格式化为 ext4 的传统 Linux 文件系统

# 系统的 CPU 数
grep 'processor' /proc/cpuinfo

如果想要知道系统还支持哪种文件系统的格式化功能,直接按 [tabl]

mkfs[tab][tab]

7.3.4 文件系统检验

如果文件系统真的发 生错乱的话,那该如何是好?就...挽救啊!不同的文件系统救援的指令不太一样

  • xfs_repair 处理 XFS 文件系统

  • fsck.ext4 处理 EXT4 文件系统

xfs_repair 或 fsck.ext4,这都是用来检查与修正文件系统错误的指令

由于 xfs_repair/fsck.ext4 在扫瞄磁盘的时候,可能会造成部分 filesystem 的修订,所以“执行 xfs_repair/fsck.ext4 时, 被检查的 partition 务必不可挂载到系统上!亦即是需要在卸载的状态喔!

7.3.5 文件系统挂载与卸载

挂载点是目录, 而这个目录是进入磁盘分区 (其实是文件系统啦!)的入口

要进行挂载前,你最好先确定几件事:

  • 单一文件系统不应该被重复挂载在不同的挂载点(目录)中;

  • 单一目录不应该重复挂载多个文件系统;

  • 要作为挂载点的目录,理论上应该都是空目录才是。

要将文件系统挂载到我们的 Linux 系统上,就要使用 mount 这个指令,umount (将设备文件卸载)

  • /etc/filesystems:系统指定的测试挂载文件系统类型的优先顺序;

  • /proc/filesystems:Linux系统已经载入的文件系统类型。

Linux 支持的文件系统 之驱动程序都写在如下的目录中:

/lib/modules/$(uname -r)/kernel/fs 目录

ext4 的驱动程序就写在 /lib/modules/$(uname -r)/kernel/fs/ext4/ 这个目录下

7.3.6 磁盘/文件系统参数修订

某些时刻,你可能会希望修改一下目前文件系统的一些相关信息,举例来说,你可能要修改 Label name , 或者是 journal 的参数,或者是其他磁盘/文件系统运行时的相关参数

  • mknod

  • xfs_admin 修改 XFS 文件系统的 UUID 与 Label name

  • tune2fs 修改 ext4 的 label name 与 UUID

7.4 设置开机挂载

7.4.1 开机挂载 /etc/fstab 及 /etc/mtab

/etc/fstab

  • 根目录 / 是必须挂载的﹐而且一定要先于其它 mount point 被挂载进来。

  • 其它 mount point 必须为已创建的目录﹐可任意指定﹐但一定要遵守必须的系统目录架构原则 (FHS)

  • 所有 mount point 在同一时间之内﹐只能挂载一次。

  • 所有 partition 在同一时间之内﹐只能挂载一次。

  • 如若进行卸载﹐您必须先将工作目录移到 mount point(及其子目录) 之外

其实 /etc/fstab (filesystem table) 就是将我们利用 mount 指令进行挂载时, 将所有的选项 与参数写入到这个文件中就是了

cat /etc/fstab
[设备/UUID等] [挂载点] [文件系统] [文件系统参数] [dump] [fsck]
  • 第一栏:磁盘设备文件名/UUID/LABEL name:

  • 第二栏:挂载点 (mount point):

  • 第三栏:磁盘分区的文件系统:

  • 第四栏:文件系统参数:

  • 第五栏:能否被 dump 备份指令作用:

  • 第六栏:是否以 fsck 检验扇区:

7.4.2 特殊设备 loop 挂载 (镜像文件不烧录就挂载使用)

7.5 内存交换空间(swap)之创建

一般来说,如果硬件的配备资源足够的话,那么 swap 应该不会被我们的系统所使用到, swap 会被利用到的时刻通常就是实体内存不足的情况了

CPU 所读取的数据都来自于内存, 那当内存不足的时候,为了让后续的程序可以顺利 的运行,因此在内存中暂不使用的程序与数据就会被挪到 swap 中了。 此时内存就会空出来 给需要执行的程序载入

由于你不 会知道何时会有大量来自网络的要求,因此最好还是能够预留一些 swap 来缓冲一下系统的内 存用量! 至少达到“备而不用”的地步

使用如下的方式来创建你的 swap

  • 设置一个 swap partition

  • 创建一个虚拟内存的文件

7.5.1 使用实体分区创建swap

7.5.2 使用文件创建swap

7.6 文件系统的特殊观察与操作

7.6.1 磁盘空间之浪费问题

一个 block 只能放置一个文件, 因此太多小文 件将会浪费非常多的磁盘容量

7.6.2 利用 GNU 的 parted 进行分区行为(Optional)

posted @ 2022-11-08 18:01  流星<。)#)))≦  阅读(161)  评论(0编辑  收藏  举报