鸟哥的linux私房菜——第七章学习(Linux 磁盘与文件系统管理)

2023-05-04,,

1.1)、文件系统特征

我们称呼一个可被挂载的数据为一个文件系统而不是一个分区!

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

每个 inode 与 block 都有编号,至于这三个数据的意义可以简略说明如下:

superblock:记录此 filesystem 的整体信息,包括inode/block的总量、使用量、剩余量, 以及文件系统的格式与相关信息等;
inode:记录文件的属性,一个文件占用一个inode,同时记录此文件的数据所在的 block 号码;
block:实际记录文件的内容,若文件太大时,会占用多个 block 。

索引式文件系统(indexed allocation)

我们将 inode 与 block 区块用图解来说明一下,如下图所示,文件系统先格式化出 inode 与 block 的区块,假设某一个文件的属性与权限数据是放置到 inode 4 号(下图较小方格内),而这个 inode 记录了文件数据的实际放置点为 2, 7, 13, 15 这四个 block 号码,此时我们的操作系统就能够据此来排列磁盘的读取顺序,可以一口气将四个 block 内容读出来! 那么数据的读取就如同下图中的箭头所指定的模样了。

inode/block 数据存取示意图

U盘的FAT格式文件系统的文件读取方式如下,),FAT 这种格式的文件系统并没有 inode 存在,所以 FAT 没有办法将这个文件的所有 block 在一开始就读取出来。每个 block 号码都记录在前一个 block 当中, 他的读取方式有点像下面这样:

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

两者之间就如同串联和并联的关系。

上图中我们假设文件的数据依序写入1->7->4->15号这四个 block 号码中, 但这个文件系统没有办法一口气就知道四个 block 的号码,他得要一个一个的将 block 读出后,才会知道下一个 block 在何处。 如果同一个文件数据写入的 block 分散的太过厉害时,则我们的磁头将无法在磁盘转一圈就读到所有的数据, 因此磁盘就会多转好几圈才能完整的读取到这个文件的内容!所以我们就需要“磁盘重组”了,磁盘重组的原因就是文件写入的 block 太过于离散了,此时文件读取的性能将会变的很差所致。这个时候可以通过磁盘重组将同一个文件所属的 blocks 汇整在一起,这样数据的读取会比较容易啊!

1.2)、Linux的EXT2文件系统(inode)

在复习一下:inode 的内容在记录文件的权限与相关属性,至于 block 区块则是在记录文件的实际内容。

而且文件系统一开始就将 inode 与 block 规划好了,除非重新格式化(或者利用 resize2fs 等指令变更文件系统大小),否则 inode 与 block 固定后就不再变动。

但是如果仔细考虑一下,如果我的文件系统高达数百GB时, 那么将所有的 inode 与 block 通通放置在一起将是很不智的决定,因为 inode 与block 的数量太庞大,不容易管理。

为此之故,因此 Ext2 文件系统在格式化的时候基本上是区分为多个区块群组 (block group) 的,每个区块群组都有独立的inode/block/superblock 系统。感觉上就好像我们在当兵时,一个营里面有分成数个连,每个连有自己的联络系统, 但最终都向营部回报连上最正确的信息一般!这样分成一群群的比较好管理啦!整个来说,Ext2 格式化后有点像下面这样:

ext2文件系统示意图

Data block(数据区块):

在 Ext2 文件系统中所支持的 block 大小有 1K, 2K 及 4K 三种,初始化太大则会造成空间浪费,太小会造成读写性能不良。合理使用block区块大小。

inode table(inode表格):

inode 的内容在记录文件的属性以及该文件实际数据是放置在哪几号 block 内!系统读取文件时需要先找到 inode,并分析 inode 所记录的权限与使用者是否符合,若符合才能够开始实际读取 block 的内容。

Inode的大小固定为128Bytes。记录一个 block 号码要花掉 4Byte。

为此我们的系统很聪明的将 inode 记录 block 号码的区域定义为12个直接,一个间接, 一个双间接与一个三间接记录区。

Inode示意图

Superblock (超级区块)

这个文件系统的基本信息都写在这里

Filesystem Description (文件系统描述说明)
block bitmap (区块对照表)
inode bitmap (inode 对照表)
dumpe2fs: 查询 Ext 家族 superblock 信息的指令

1.3)、与目录树的关系

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

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

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

【读取某文件时系统的步骤】

如果我想要读取 /etc/passwd 这个文件时,系统是如何读取的呢?

[root@study ~]# 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

步骤:

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 内容的数据读出来。

【新建某文件/目录时系统的步骤】

需要用到block bitmap和inode bitmap;

假设我们想要新增一个文件,此时文件系统的行为是:

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)状态引发了 日志式文件系统(Journaling filesystem)的兴起。

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

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

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

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

1.4)、Linux 文件系统的运行

我们知道所有的数据都得要载入到内存后 CPU 才能够对该数据进行处理,那么试想如果经常编辑一个大文件,在编辑过程中有需要频繁地要系统来写入磁盘中,由于磁盘写入的速度要比内存慢很多,因此常常会耗在等待磁盘的读写时间上,效率很低。

因此,Linux使用了一个异步处理方式(asynchronously):当系统载入一个文件到内存后,如果该文件没有被更改过,则在内存区段的文件数据会被设置为干净的(clean),但如果内存中的文件数据被更改过( 如使用nano、vim等编辑过)此时就会被设置为脏的(dirty)。此时所有的动作都还在内存中执行,并没有写入到磁盘中,系统会不定时的将内存中设置为dirty的数据写回磁盘,以保持磁盘与内存数据的一致性。此外还可以利用sync指令来手动强制同步,将数据写入磁盘。

1.5)、挂载点(mount point)

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

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

为了便于大家理解,在这里再次将目录树的架构图放在这里。

如果想要查看挂载点:需要输入:ls -lid 目录名 即可。如:

1.6)、文件系统由EXT4改为XFS

因此,从 CentOS 7.x 开始, 文件系统已经由默认的 Ext4 变成了xfs 这一个较适合大容量磁盘与巨型文件性能较佳的文件系统了。

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

数据区 (data section)

该区分为多个储存区群组 (allocation groups) 来分别放置文件系统所需要的数据,每个储存区群组都包含了 (1)整个文件系统的 superblock,(2)剩余空间的管理机制,(3)inode的分配与追踪。此外,inode与 block 都是系统需要用到时, 这才动态配置产生,所以格式化动作超级快。

文件系统活动登录区 (log section)

主要被用来纪录文件系统的变化,像是日志区。文件的变化会在这里记录下来,直到该变化 完整的写入到数据区后,该笔记录才会被终结。

实时运行区 (realtime section)

当有文件要被创建时,xfs 会在这个区段里面找一个到数个的 extent 区块,将文件放置在这个区块内,等到分配完毕后,再写入到data section 的 inode 与 block 去。

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

解释:

l 第一行isize指的是inode的容量,每个有256Bytes这么大,agcount指的是存储区群组(allocation group)的个数,有4个,agsize指的是每个存储区群组具有65536个block,结合第四行bsize=4096Bytes=4k,故整个系统文件的容量就是4*65536*4k的大小。

l 第二行的sectsz=512指的是逻辑扇区(sector)的容量大小;

l 第七行internal指的是该登录区的位置在文件系统内而不是外部设备的意思,且占用了4k*2560个block,共约10M的容量。

2.0)、磁盘与目录的容量

现在我们知道磁盘的整体数据是在 superblock 区块中,但是每个各别文件的容量则在 inode 当中记载的。文本界面下面该如何叫出这几个数据呢?有两个指令:

df:列出文件系统的整体磁盘使用量;
du:评估文件系统的磁盘使用量(常用在推估目录所占容量)

范例一:将容量结果以易读的容量格式显示出来

[root@study ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/centos-root 10G 3.3G 6.8G 33% /
devtmpfs 613M 0 613M 0% /dev
tmpfs 623M 80K 623M 1% /dev/shm
tmpfs 623M 25M 599M 4% /run
tmpfs 623M 0 623M 0% /sys/fs/cgroup
/dev/mapper/centos-home 5.0G 67M 5.0G 2% /home
/dev/vda2 1014M 131M 884M 13% /boot

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

2.1)、实体链接与符号链接:ln

在linux下链接文件有两种:一种是类似Windows的捷径功能的文件,可以快速的链接到目标文件或目录;另一种是通过文件系统的inode链接来产生新的文件名(注意不是产生新文件),这种叫做实体链接(hard link)。

hard link实体链接,硬式链接或实际链接

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

当多个文件名对应到同一个 inode 号码时就是 hard link了,即hard link 只是在某个目录下新增一笔文件名链接到某 inode 号码的关连记录而已。

事实上 hard link 应该仅能在单一文件系统中进行的,故hard link也有一些限制:

不能跨 Filesystem;
不能 link 目录。
Sysbolic link符号链接,即捷径

Symbolic link 就是在创建一个独立的文件,而这个文件会让数据的读取指向他 link 的那个文件的文件名!

举个例子:先创建一个符号链接文件链接到 /etc/crontab

[root@study ~]# ln -s /etc/crontab crontab2
[root@study ~]# ll -i /etc/crontab /root/crontab2
34474855 -rw-r--r--. 2 root root 451 Jun 10 2014 /etc/crontab
53745909 lrwxrwxrwx. 1 root root 12 Jun 23 22:31 /root/crontab2 -> /etc/crontab

解释:

由 1 号 inode 读取到链接文件的内容仅有文件名,根据文件名链接到正确的目录去取得目标文件的inode , 最终就能够读取到正确的数据了。你可以发现的是,如果目标文件(/etc/crontab)被删除了,那么整个环节就会无法继续进行下去, 所以就会发生无法通过链接文件读取的问题了!

这里还是得特别留意,这个 Symbolic Link 与 Windows 的捷径可以给他划上等号,由 Symbolic link 所创建的文件为一个独立的新的文件,所以会占用掉 inode 与 block 喔!

而对于hard link 来说,当某一个目录下的关联数据被杀掉后,也没有关系,可以通过其他目录下存在的关联数据来访问,所以该数据就不会不被见。即多重保障。

另:Symbolic link会占用掉inode和block,而hard link则不占用。

事例:

[root@study ~]# ln [-sf] 来源文件 目标文件

选项与参数:

-s :如果不加任何参数就进行链接,那就是hard link,至于 -s 就是symbolic link

-f :如果 目标文件 存在时,就主动的将目标文件直接移除后再创建!

范例一:将 /etc/passwd 复制到 /tmp 下面,并且观察 inode 与 block

[root@study ~]# cd /tmp
[root@study tmp]# cp -a /etc/passwd .
[root@study tmp]# du -sb ; df -i .
6602 . <==先注意一下这里的容量是多少!
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/mapper/centos-root 10485760 109748 10376012 2% /
# 利用 du 与 df 来检查一下目前的参数~那个 du -sb 是计算整个 /tmp 下面有多少 Bytes 的容量啦! 范例二:将 /tmp/passwd 制作 hard link 成为 passwd-hd 文件,并观察文件与容量
[root@study tmp]# ln passwd passwd-hd
[root@study tmp]# du -sb ; df -i .
6602 .
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/mapper/centos-root 10485760 109748 10376012 2% /

# 仔细看,即使多了一个文件在 /tmp 下面,整个 inode 与 block 的容量并没有改变!

[root@study tmp]# ls -il passwd*
2668897 -rw-r--r--. 2 root root 2092 Jun 17 00:20 passwd
2668897 -rw-r--r--. 2 root root 2092 Jun 17 00:20 passwd-hd
# 原来是指向同一个 inode 啊!这是个重点啊!另外,那个第二栏的链接数也会增加!

范例三:将 /tmp/passwd 创建一个符号链接

[root@study tmp]# ln -s passwd passwd-so
[root@study tmp]# ls -li passwd*
2668897 -rw-r--r--. 2 root root 2092 Jun 17 00:20 passwd
2668897 -rw-r--r--. 2 root root 2092 Jun 17 00:20 passwd-hd
2668898 lrwxrwxrwx. 1 root root 6 Jun 23 22:40 passwd-so -> passwd
# passwd-so 指向的 inode number 不同了!这是一个新的文件~这个文件的内容是指向
# passwd 的。passwd-so 的大小是 6Bytes ,因为 “passwd” 这个单字共有六个字符之故
[root@study tmp]# du -sb ; df -i .
6608 .
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/mapper/centos-root 10485760 109749 10376011 2% /
# 呼呼!整个容量与 inode 使用数都改变啰~确实如此啊!

范例四:删除原始文件 passwd ,其他两个文件是否能够打开?

[root@study tmp]# rm passwd
[root@study tmp]# cat passwd-hd
.....(正常显示完毕!)
[root@study tmp]# cat passwd-so
cat: passwd-so: No such file or directory
[root@study tmp]# ll passwd*
-rw-r--r--. 1 root root 2092 Jun 17 00:20 passwd-hd
lrwxrwxrwx. 1 root root 6 Jun 23 22:40 passwd-so -> passwd
# 怕了吧!符号链接果然无法打开!另外,如果符号链接的目标文件不存在,
# 其实文件名的部分就会有特殊的颜色显示

2.2)、磁盘

如果我们想要在系统里面新增一颗磁盘时,应该做如下:

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

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

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

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

观察磁盘分区状态lsblkblkid,parted 

lsblk list block device,即列出系统上的所有磁盘列表。

blkid :列出设备的UUID等参数;

parted 列出磁盘的分区表类型和分区信息:parted /dev/vda print

磁盘分区gdisk,fdisk 

特别注意:MBR 分区表请使用 fdisk 分区, GPT 分区表请使用 gdisk 分区!

磁盘格式化mkfs 

创建文件系统 (make filesystem)

XFS 文件系统 mkfs.xfs
EXT4 文件系统 mkfs.ext4

2.3)、文件系统挂载与卸载

挂载前需要确定:

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

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

3、要作为挂载点的目录,理论上应该都是空目录才是。如果你要用来挂载的目录里面并不是空的,那么挂载了文件系统之后,原目录下的东西就会暂时的消失。

重新挂载根目录与挂载不特定目录

范例:将 / 重新挂载,并加入参数为 rw 与 auto

[root@study ~]# mount -o remount,rw,auto /

重点是那个“ -o remount,xx ”的选项与参数,尤其是当你进入单人维护模式时,你的根目录常会被系统挂载为只读,这个时候这个指令就太重要了!

本章节回顾:

l 一个可以被挂载的数据通常称为“文件系统, filesystem”而不是分区 (partition) 喔

l 基本上 Linux 的传统文件系统为 Ext2 ,该文件系统内的信息主要有:

superblock:记录此 filesystem 的整体信息,包括inode/block的总量、使用量、剩余量, 以及文件系统的格式与相关信息等;
inode:记录文件的属性,一个文件占用一个inode,同时记录此文件的数据所在的 block 号码;
block:实际记录文件的内容,若文件太大时,会占用多个 block 。

l Ext2 文件系统的数据存取为索引式文件系统(indexed allocation)

l 需要磁盘重组的原因就是文件写入的 block 太过于离散了,此时文件读取的性能将会变的很差所致。 这个时候可以通过磁盘重组将同一个文件所属的 blocks 汇整在一起。

l Ext2文件系统主要有:boot sector, superblock, inode bitmap, block bitmap, inode table, data block 等六大部分。

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

l inode 记录文件的属性/权限等数据,其他重要项目为: 每个 inode 大小均为固定,有 128/256Bytes 两种基本容量。每个文件都仅会占用一个 inode 而已; 因此文件系统能够创建的文件数量与 inode 的数量有关;

l 文件的 block 在记录文件的实际数据,目录的 block 则在记录该目录下面文件名与其 inode 号码的对照表;

l 日志式文件系统 (journal) 会多出一块记录区,随时记载文件系统的主要活动,可加快系统复原时间;

l Linux 文件系统为增加性能,会让内存作为大量的磁盘高速缓存;

l 实体链接只是多了一个文件名对该 inode 号码的链接而已;

l 符号链接就类似Windows的捷径功能。

l 磁盘的使用必需要经过:分区、格式化与挂载,分别惯用的指令为:gdisk, mkfs, mount三个指令;

l 分区时,应使用 parted 检查分区表格式,再判断使用 fdisk/gdisk 来分区,或直接使用 parted 分区;

l 为了考虑性能,XFS 文件系统格式化时,可以考虑加上 agcount/su/sw/extsize 等参数较佳;

l 如果磁盘已无未分区的容量,可以考虑使用大型文件取代磁盘设备的处理方式,通过 dd 与格式化功能。

l 开机自动挂载可参考/etc/fstab之设置,设置完毕务必使用 mount -a 测试语法正确否。

Over...

鸟哥的linux私房菜——第七章学习(Linux 磁盘与文件系统管理)的相关教程结束。

《鸟哥的linux私房菜——第七章学习(Linux 磁盘与文件系统管理).doc》

下载本文的Word格式文档,以方便收藏与打印。