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

 

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 内容读出来! 那么数据的读取就如同下图中的箭头所指定的模样了。

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

inode/block 数据存取示意图

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

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

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 格式化后有点像下面这样:

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

ext2文件系统示意图

  • Data block(数据区块):

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

  • inode table(inode表格):

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

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

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

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

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等信息,这个文件要能够链接到目录树才能够被我们使用。而将文件系统和目录树结合的动作我们称之为 “挂载”。

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

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

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

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

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

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文件系统的描述数据观察

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

解释:

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系统编程【4】——文件系统


下一篇:Linux ln 命令