为什么linux中df的df 文件系统统,比blkid多很多

linux学习笔记——linux磁盘与文件系统管理
认识linux文件系统
以GPT分区为主来介绍
文件系统特性
较新的操作系统的文件数据除了文件实际内容外, 通常含有非常多的属性,例如 Linux
操作系统的文件权限(rwx)与文件属性(拥有者、群组、时间参数等)。文件系统通常会将这两部份的数据分别存放在不同的区块,权限与属性放置到inode
中,至于实际数据则放置到 data block 区块中。 另外,还有一个超级区块
(superblock)会记录整个文件系统的整体信息,包括 inode 与 block 的总量、使用量、剩余量等。
每个 inode 与 block 都有编号,至于这三个数据的意义可以简略说明如下:
 superblock:记录此 filesystem 的整体信息,包括 inode/block
的总量、使用量、剩余量,以及文件系统的格式与相关信息等;
 inode:记录文件的属性,一个文件占用一个 inode,同时记录此文件的数据所在的 block 号码;
 block:实际记录文件的内容,若文件太大时,会占用多个 block 。
由于每个 inode 与 block 都有编号,而每个文件都会占用一个 inode ,inode 内则有文件数据放置的 block
号码。 因此,我们可以知道的是,如果能够找到文件的 inode 的话,那么自然就会知道这个文件所放置数据的 block
号码,当然也就能够读出该文件的实际数据了。这是个比较有效率的作法,因为如此一来我们的磁盘就能够在短时间内读取出全部的数据,读写的效能比较好。
这种数据存取的方法我们称为索引式文件系统(indexed allocation)。我们惯用的随身碟(闪存),随身碟使用的文件系统一般为
FAT 格式。FAT 这种格式的文件系统并没有 inode 存在,所以 FAT 没有办法将这个文件的所有 block
在一开始就读取出来。每个 block 号码都记录在前一个 block 当中, 他的读取方式有点像这样:我们假设文件的数据依序写入
1-&7-&4-&15 号这四个 block 号码中, 但这个文件系统没有办法一口气就知道四个 block
的号码,他得要一个一个的将 block 读出后,才会知道下一个 block 在何处。 如果同一个文件数据写入的 block
分散的太过厉害时,则我们的磁盘读取头将无法在磁盘转一圈就读到所有的数据,因此磁盘就会多转好几圈才能完整的读取到这个文件的内容!
常常会听到所谓的『碎片整理』, 需要碎片整理的原因就是文件写入的 block
太过于离散了,此时文件读取的效能将会变的很差所致。这个时候可以透过碎片整理将同一个文件所属的 blocks
汇整在一起,这样数据的读取会比较容易! FAT 的文件系统需要经常的碎片整理一下。
是索引式文件系统,基本上不太需要常常进行碎片整理的。但是如果文件系统使用太久,常常删除/编辑/新增文件时,那么还是可能会造成文件数据太过于离散的问题,此时或许会需要进行重整一下的。一般来说Ext2/Ext3
不需要碎片整理。
Linux 的 EXT2 文件系统(inode)
如同前面所说的,inode 的内容在记录文件的权限与相关属性,至于 block
区块则是在记录文件的实际内容。而且文件系统一开始就将 inode 与 block 规划好了,除非重新格式化(或者利用resize2fs
等指令变更文件系统大小),否则 inode 与 block 固定后就不再变动。但是如果仔细考虑一下,如果我的文件系统高达数百 GB
时, 那么将所有的 inode 与 block 通通放置在一起将是很不智的决定,因为 inode 与 block
的数量太庞大,不容易管理。
为此之故,因此 Ext2 文件系统在格式化的时候基本上是区分为多个区块群组 (block group)
的,每个区块群组都有独立的 inode/block/superblock 系统。
在整体的规划当中,文件系统最前面有一个启动扇区(boot
sector),这个启动扇区可以安装开机管理程序,这是个非常重要的设计,因为如此一来我们就能够将不同的开机管理程序安装到个别的文件系统最前端,而不用覆盖整颗磁盘唯一的
MBR,这样也才能够制作出多重引导的环境啊!至于每一个区块群组(block group)的六个主要内容说明如后:
 data block (资料区块)
data block 是用来放置文件内容数据地方,在 Ext2 文件系统中所支持的 block 大小有 1K, 2K 及4K
三种而已。在格式化时 block 的大小就固定了,且每个 block 都有编号,以方便 inode 的记录。不过要注意的是,由于
block 大小的差异,会导致该文件系统能够支持的最大磁盘容量与最大单一文件容量并不相同。 因为 block 大小而产生的 Ext2
文件系统限制如下:
大小&&&&&&&&&&&&&&&&&&&&&&&
1KB&&&&&&&&&
2KB&&&&&&&&&&&
最大单一文件限制&&&&&&&&&&&&
256GB&&&&&&&&&
最大文件系统总容量&&&&&&&&&
2TB&&&&&&&&&
8TB&&&&&&&&&&&
需要注意的是,虽然 Ext2 已经能够支持大于 2GB
以上的单一文件容量,不过某些应用程序依然使用旧的限制,也就是说,某些程序只能够捉到小于 2GB
以下的文件而已,这就跟文件系统无关了!
除此之外 Ext2 文件系统的 block 还有什么限制呢?有的!基本限制如下:
 原则上,block 的大小与数量在格式化完就不能够再改变了(除非重新格式化);
 每个 block 内最多只能够放置一个文件的数据;
 承上,如果文件大于 block 的大小,则一个文件会占用多个 block 数量;
 承上,若文件小于 block ,则该 block 的剩余容量就不能够再被使用了(磁盘空间会浪费)。
如上第四点所说,由于每个 block 仅能容纳一个文件的数据而已,因此如果你的文件都非常小,但是你的 block
在格式化时却选用最大的 4K 时,可能会产生一些容量的浪费
 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 的内容。
分析一下 EXT2 的 inode / block 与文件大小的关系。inode 要记录的数据非常多,但偏偏又只有 128bytes
而已, 而 inode 记录一个 block 号码要花掉 4byte ,假设我一个文件有400MB 且每个 block 为 4K
时,那么至少也要十万笔 block 号码的记录!为此我们的系统很聪明的将 inode 记录 block 号码的区域定义为 12
个直接,一个间接, 一个双间接与一个三间接记录区。
这样子 inode 能够指定多少个 block 呢?我们以较小的 1K block 来说明,可以指定的情况如下:
 12 个直接指向: 12*1K=12K
由于是直接指向,所以总共可记录 12 笔记录,因此总额大小为如上所示;
 间接: 256*1K=256K
每笔 block 号码的记录会花去 4bytes,因此 1K 的大小能够记录 256
笔记录,因此一个间接可以记录的文件大小如上;
 双间接: 256*256*1K=2562K
第一层 block 会指定 256 个第二层,每个第二层可以指定 256 个号码,因此总额大小如上;
 三间接: 256*256*256*1K=2563K
第一层 block 会指定 256 个第二层,每个第二层可以指定 256 个第三层,每个第三层可以指定 256 个号
码,因此总额大小如上;
 总额:将直接、间接、双间接、三间接加总,得到 12 + 256 + 256*256 + 256*256*256 (K) =
此时我们知道当文件系统将 block 格式化为 1K 大小时,能够容纳的最大文件为
16GB,比较一下文件系统限制表的结果可发现是一致的!但这个方法不能用在 2K 及 4K block 大小的计算中, 因为大于 2K
的 block 将会受到 Ext2 文件系统本身的限制,所以计算的结果会不太符合之故。
 Superblock (超级区块)
Superblock 是记录整个 filesystem 相关信息的地方,没有 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 是非常重要的,因为我们这个文件系统的基本信息都写在这里,因此,如果 superblock
死掉了,你的文件系统可能就需要花费很多时间去挽救!一般来说,superblock 的大小为 1024bytes。相关的
superblock 讯息我们等一下会以 dumpe2fs 指令来呼叫出来观察!
此外,每个 block group 都可能含有 superblock !但是我们也说一个文件系统应该仅有一个superblock
而已, 事实上除了第一个 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 号码就得要释放出来, 此时在block bitmap 当中相对应到该
block 号码的标志就得要修改成为『未使用中』!这就是 bitmap 的功能。
 inode bitmap (inode 对照表)
这个其实与 block bitmap 是类似的功能,只是 block bitmap 记录的是使用与未使用的 block 号码,至于
inode bitmap 则是记录使用与未使用的 inode 号码!
 dumpe2fs: 查询 Ext 家族 superblock 信息的指令
刚刚谈到的各部分数据都与 block 号码有关!每个区段与 superblock 的信息都可以使用 dumpe2fs
这个指令来查询的!不过很可惜的是,CentOS 7 现在是以 xfs 为预设文件系统, 所以目前你的系统应该无法使用 dumpe2fs
去查询任何文件系统的。你可以在后续的格式化内容讲完之后,自己切出一个 ext4 的文件系统去查询看看。之后的这块文件系统是 1GB
的容量,使用默认方式来进行格式化的, 观察的内容如下:
# dumpe2fs [-bh] 装置文件名
-b :列出保留为坏轨的部分(一般用不到吧!?)
-h :仅列出 superblock 的数据,不会列出其他的区段内容!
范例:一块 1GB ext4 文件系统内容
[root@study ~]# blkid &==这个指令可以叫出目前系统有被格式化的装置
/dev/vda5: UUID="e20d65d9-20d4-472f-9f91-cdcfb30219d6" TYPE="ext4"
&==看到 ext4 了!
[root@study ~]# dumpe2fs /dev/vda5
dumpe2fs 1.42.9 (28-Dec-2013)
Filesystem volume name: # 文件系统的名称(不一定会有)
Last mounted on: # 上一次挂载的目录位置
Filesystem UUID: e20d65d9-20d4-472f-9f91-cdcfb30219d6
Filesystem magic number: 0xEF53 # 上方的 UUID 为 Linux 对装置的定义码
Filesystem revision #: 1 (dynamic) # 下方的 features 为文件系统的特征数据
Filesystem features: has_journal ext_attr resize_inode dir_index
filetype extent 64bit
& flex_bg sparse_super large_file huge_file
uninit_bg dir_nlink extra_isize
Filesystem flags: signed_directory_hash
Default mount options: user_xattr acl # 预设在挂载时会主动加上的挂载参数
Filesystem state: clean # 这块文件系统的状态为何,clean 是没问题
Errors behavior: Continue
Filesystem OS type: Linux
Inode count: 65536 # inode 的总数
Block count: 262144 # block 的总数
Reserved block count: 13107 # 保留的 block 总数
Free blocks: 249189 # 还有多少的 block 可用数量
Free inodes: 65525 # 还有多少的 inode 可用数量
First block: 0
Block size: 4096 # 单个 block 的容量大小
Fragment size: 4096
Group descriptor size: 64
....(中间省略)....
Inode size: 256 # inode 的容量大小!已经是 256 了喔!
....(中间省略)....
Journal inode: 8
Default directory hash: half_md4
Directory Hash Seed: 3ca7e-44cf-95a2-c8867fb19fbc
Journal backup: inode blocks
Journal features: (none)
Journal size: 32M # Journal 日志式数据的可供纪录总容量
Journal length: 8192
Journal sequence: 0x
Journal start: 0
Group 0: (Blocks 0-32767) # 第一块 block group 位置
& Checksum 0x13be, unused inodes 8181
& Primary superblock at 0, Group descriptors at
1-1 # 主要 superblock 的所在!
Reserved GDT blocks at 2-128
&Block bitmap at 129 (+129), Inode bitmap at 145
&Inode table at 161-672 (+161) # inode table
的所在喔!
&28521 free blocks, 8181 free inodes, 2
directories, 8181 unused inodes
&Free blocks: 142-144, 153-160,
底下两行说明剩余的容量有多少
&Free inodes: 12-8192
Group 1: (Blocks ) [INODE_UNINIT] # 后续为更多其他的 block group
....(底下省略)....
# 由于数据量非常的庞大,因此将一些信息省略输出了!上表与你的屏幕会有点差异。前半部在秀出 supberblock
的内容,包括标头名称(Label)以及 inode/block 的相关信息后面则是每个 block group
的个别信息了!您可以看到各区段数据所在的号码!也就是说,基本上所有的数据还是与 block 的号码有关就是了!很重要!
如上所示,利用 dumpe2fs 可以查询到非常多的信息,不过依内容主要可以区分为上半部是superblock 内容, 下半部则是每个
block group 的信息了。从上面的表格中我们可以观察到这个 /dev/vda5 规划的 block 为 4K, 第一个
block 号码为 0 号,且 block group 内的所有信息都以block 的号码来表示的。然后在 superblock
中还有谈到目前这个文件系统的可用 block 与 inode 数量!
至于 block group 的内容我们单纯看 Group0 信息。从上表中我们可以发现:
 Group0 所占用的 block 号码由 0 到 32767 号,superblock 则在第 0 号的 block
 文件系统描述说明在第 1 号 block 中;
 block bitmap 与 inode bitmap 则在 129 及 145 的 block 号码上。
 至于 inode table 分布于 161-672 的 block 号码中!
 由于一个 inode 占用 256 bytes,总共有 672 - 161 + 1(161 本身) = 512 个 block
花在 inode table 上,每个 block 的大小为 4096 bytes(4K)。由这些数据可以算出 inode 的数量共有
512 * 4096 / 256 = 8192个inode!
 这个 Group0 目前可用的 block 有 28521 个,可用的 inode 有 8181 个;
 剩余的 inode 号码为 12 号到 8192 号。
与目录树的关系
由前一小节的介绍我们知道在 Linux 系统下,每个文件(不管是一般文件还是目录文件)都会占用一个inode
,且可依据文件内容的大小来分配多个 block
给该文件使用。而由权限说明中我们知道目录的内容在记录文件名,一般文件才是实际记录数据内容的地方。那么目录与文件在文件系统当中是如何记录数据的呢?基本上可以这样说:
 目录
当我们在 Linux 下的文件系统建立一个目录时,文件系统会分配一个 inode 与至少一块 block 给该目录。其中,inode
记录该目录的相关权限与属性,并可记录分配到的那块 block 号码; 而 block 则是记录在这个目录下的文件名与该文件名占用的
inode 号码数据。
如果想要实际观察 root 家目录内的文件所占用的 inode 号码时,可以使用 ls -i 这个选项来处理:
-rw-------. 1 root root 1816 May 4 17:57
anaconda-ks.cfg
-rw-r--r--. 1 root root 1864 May 4 18:01
initial-setup-ks.cfg
由于每个人所使用的计算机并不相同,系统安装时选择的项目与 partition
都不一样,因此&inode 号码不可能一模一样!由这个目录的 block
结果我们现在就能够知道,当你使用『 ll / 』时,出现的目录几乎都是 1024 的倍数,因为每个 block 的数量都是 1K,
2K, 4K !:
[root@study ~]# ll -d / /boot /usr/sbin /proc /sys
dr-xr-xr-x. 17 root root 4096 May 4 17:56 / &== 1 个 4K
dr-xr-xr-x. 4 root root 4096 May 4 17:59 /boot &== 1 个 4K
dr-xr-xr-x. 155 root root 0 Jun 15 15:43 /proc &==
这两个为内存内数据,不占磁盘容量
dr-xr-xr-x. 13 root root 0 Jun 15 23:43 /sys
dr-xr-xr-x. 2 root root 16384 May 4 17:55 /usr/sbin &== 4 个 4K
由于根目录使用的 block 大小为 4K ,因此每个目录几乎都是 4K 的倍数。 其中由于/usr/sbin
的内容比较复杂因此占用了 4 个 block !至于奇怪的 /proc 我们讲过该目录不占磁盘容量, 所以耗用的 block 就是 0
 文件:
当我们在 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 这个文件:
[root@study ~]# ll -di / /etc /etc/passwd
&128 dr-xr-xr-x. 17 root root 4096 May 4 17:56
drwxr-xr-x. 131 root root 8192 Jun 17 00:20 /etc
-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 号码 ();
3. etc/ 的 inode:
号 inode 得知 dmtsai 具有 r 与 x 的权限,因此可以读取 etc/ 的 block
4. etc/ 的 block:
经过上个步骤取得 block 号码,并找到该内容有 passwd 文件的 inode 号码 ();
5. passwd 的 inode:
号 inode 得知 dmtsai 具有 r 的权限,因此可以读取 passwd 的 block
6. passwd 的 block:
最后将该 block 内容的数据读出来。
 filesystem 大小与磁盘读取效能:
另外,关于文件系统的使用效率上,当你的一个文件系统规划的很大时,例如 100GB
这么大时,由于磁盘上面的数据总是来来去去的,所以,整个文件系统上面的文件通常无法连续写在一起(block
号码不会连续的意思),而是填入式的将数据填入没有被使用的 block 当中。如果文件写入的 block
真的分的很散,此时就会有所谓的文件数据离散的问题发生了。
如前所述,虽然我们的 ext2 在 inode 处已经将该文件所记录的 block
号码都记上了,所以资料可以一次性读取,但是如果文件真的太过离散,确实还是会发生读取效率低落的问题。因为磁盘读取头还是得要在整个文件系统中来来去去的频繁读取!果真如此,那么可以将整个
filesystme 内的数据全部复制出来,将该 filesystem 重新格式化,再将数据给他复制回去即可解决这个问题。
此外,如果 filesystem 真的太大了,那么当一个文件分别记录在这个文件系统的最前面与最后面的block
号码中,此时会造成磁盘的机械手臂移动幅度过大,也会造成数据读取效能的低落。而且读取头在搜寻整个 filesystem
时,也会花费比较多的时间去搜寻!因此, partition 的规划并不是越大越好
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 这支程序来进行的。
不过,这样的检查真的是很费时,因为要针对 metadata 区域与实际数据存放区来进行比对,得要搜寻整个
filesystem,而且在对 Internet
提供服务的服务器主机上面,这样的检查真的会造成主机复原时间的拉长,这也就造成后来所谓日志式文件系统的兴起了。
 日志式文件系统 (Journaling filesystem)
为了避免上述提到的文件系统不一致的情况发生,因此我们的前辈们想到一个方式, 如果在我们的filesystem
当中规划出一个区块,该区块专门在记录写入或修订文件时的步骤,也就是说:
1. 预备:当系统要写入一个文件时,会先在日志记录区块中纪录某个文件准备要写入的信息;
2. 实际写入:开始写入文件的权限与数据;开始更新 metadata 的数据;
3. 结束:完成数据与 metadata 的更新后,在日志记录区块当中完成该文件的纪录。
在这样的程序当中,万一数据的纪录过程当中发生了问题,那么我们的系统只要去检查日志记录区块,就可以知道哪个文件发生了问题,针对该问题来做一致性的检查即可,而不必针对整块
filesystem 去检查, 这样就可以达到快速修复 filesystem 的能力了!这就是日志式文件最基础的功能
ext2可以透过 ext3/ext4 达到这样的功能!ext3/ext4 是 ext2 的升级版本,并且可向下兼容 ext2
版本!所以我们可以直接使用 ext4 这个filesystem !如果你还记得 dumpe2fs 输出的讯息,可以发现
superblock 里面含有底下这样的信息:
Journal inode: 8
Journal backup: inode blocks
Journal features: (none)
Journal size: 32M
Journal length: 8192
Journal sequence: 0x
透过 inode 8 号记录 journal 区块的 block 指向,而且具有 32MB 的容量在处理日志!
&Linux 文件系统的运作
我们现在知道了目录树与文件系统的关系了,但我们也知道, 所有的数据都得要加载到内存后 CPU
才能够对该数据进行处理。想一想,如果你常常编辑一个好大的文件,在编辑的过程中又频繁的要系统来写入到磁盘中,由于磁盘写入的速度要比内存慢很多,因此你会常常耗在等待磁盘的写入/读取上。
为了解决这个效率的问题,因此我们的 Linux 使用的方式是透过一个称为异步处理 (asynchronously)
的方式。所谓的异步处理是这样的:
当系统加载一个文件到内存后,如果该文件没有被更动过,则在内存区段的文件数据会被设定为干净(clean)的。但如果内存中的文件数据被更改过了(例如你用
nano 去编辑过这个文件),此时该内存中的数据会被设定为脏的
(Dirty)。此时所有的动作都还在内存中执行,并没有写入到磁盘中!系统会不定时的将内存中设定为『Dirty』的数据写回磁盘,以保持磁盘与内存数据的一致性。也可以利用sync
指令来手动强迫写入磁盘。
我们知道内存的速度要比磁盘快的多,因此如果能够将常用的文件放置到内存当中,就会增加系统性能,因此 Linux
系统上面文件系统与内存有非常大的关系:
 系统会将常用的文件数据放置到主存储器的缓冲区,以加速文件系统的读/写;
 承上,因此 Linux 的物理内存最后都会被用光!这是正常的情况!可加速系统效能;
 你可以手动使用 sync 来强迫内存中设定为 Dirty 的文件回写到磁盘中;
 若正常关机时,关机指令会主动呼叫 sync 来将内存的数据回写入磁盘内;
但若不正常关机(如跳电、当机或其他不明原因),由于数据尚未回写到磁盘内,因此重新启动后可能会花很多时间在进行磁盘检验,甚至可能导致文件系统的损毁(非磁盘损毁)。
&&& 挂载点的意义
(mount point)
每个 filesystem 都有独立的 inode / block / superblock
等信息,这个文件系统要能够链接到目录树才能被使用。将文件系统与目录树结合的动作称为『挂载』。重点是:挂载点一定是目录,该目录为进入该文件系统的入口。因此并不是你有任何文件系统都能使用,必须要『挂载』到目录树的某个目录后,才能够使用该文件系统的。
观察这三个目录的 inode 号码时,可以发现如下的情况:
[root@study ~]# 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
号码来确认不同文件名是否为相同的文件!所以可以这样看:
[root@study ~]# 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
号码,当然这三个文件的内容也就完全一模一样了!也就是说,根目录的上层 (/..) 就是他自己!
Linux 支持的文件系统与 VFS
虽然 Linux 的标准文件系统是 ext2 ,且还有增加了日志功能的 ext3/ext4 ,事实上,Linux
还有支持很多文件系统格式的, 尤其是最近这几年推出了好几种速度很快的日志式文件系统,包括 SGI 的XFS
文件系统,可以适用更小型文件的 Reiserfs 文件系统,以及 Windows 的 FAT 文件系统等等,都能够被 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 会主动的帮我们做好读取的动作
假设你的 / 使用的是 /dev/hda1 ,用 ext3 ,而 /home 使用 /dev/hda2 ,用 reiserfs
,那么你取用/home/dmtsai/.bashrc 时,有特别指定要用的什么文件系统的模块来读取吗? 应该是没有吧!这个就是 VFS
的功能!透过这个 VFS 的功能来管理所有的 filesystem, 省去我们需要自行设定读取文件系统的定义。整个 VFS
可以约略用下图来说明:
文件系统简介
CentOS 7 开始,预设的文件系统已经由原本的 EXT4 变成了 XFS 文件系统了!
 EXT 家族当前较伤脑筋的地方:支持度最广,但格式化超慢!
Ext 文件系统家族对于文件格式化的处理方面,采用的是预先规划出所有的 inode/block/meta data
等数据,未来系统可以直接取用, 不需要再进行动态配置的作法。这个作法在早期磁盘容量还不大的时候还算 OK
没啥问题,但时至今日,磁盘容量越来越大,连传统的 MBR 都已经被 GPT 所取代,当你的 TB 以上等级的传统 ext
家族文件系统在格式化的时候,光是系统要预先分配 inode 与 block 就消耗好多好多的时间了。
另外,由于虚拟化的应用越来越广泛,而作为虚拟化磁盘来源的巨型文件 (单一文件好几个 GB 以上)
也就越来越常见了。这种巨型文件在处理上需要考虑到效能问题,否则虚拟磁盘的效率就会不太好看。因此,从 CentOS 7.x
开始,文件系统已经由预设的 Ext4 变成了 xfs 这一个较适合高容量磁盘与巨型文件效能较佳的文件系统了。
 XFS 文件系统的配置
基本上 xfs 就是一个日志式文件系统,而 CentOS 7.x 拿它当预设的文件系统,就是因为最早之前,这个 xfs
就是被开发来用于高容量磁盘以及高性能文件系统之用,相当适合现在的系统环境。此外,几乎所有 Ext4 文件系统有的功能, xfs
都可以具备!
xfs 文件系统在资料的分布上,主要规划为三个部份,一个资料区 (data section)、一个文件系统活动登录区 (log
section)以及一个实时运作区 (realtime section)。 这三个区域的数据内容如下:
o 资料区 (data section)
基本上,数据区就跟我们之前谈到的 ext 家族一样,包括 inode/data block/superblock
等数据,都放置在这个区块。 这个数据区与 ext 家族的 block group 类似,也是分为多个储存区群组(allocation
groups) 来分别放置文件系统所需要的数据。 每个储存区群组都包含了整个文件系统的
superblock、剩余空间的管理机制、inode
的分配与追踪。此外,inode与block都是系统需要用到时,这才动态配置产生,所以格式化动作超级快。
另外,与 ext 家族不同的是, xfs 的 block 与 inode 有多种不同的容量可供设定,block 容量可由
512bytes ~ 64K 调配,不过,Linux 的环境下, 由于内存控制的关系 (页面文件 pagesize
的容量之故),因此最高可以使用的 block 大小为 4K 而已。至于 inode 容量可由 256bytes 到 2M
这么大!不过,大概还是保留 256bytes 的默认值就很够用了!
Tips 总之, xfs 的这个数据区的储存区群组 (allocation groups, AG),你就将它想成是 ext 家族的
block 群组 (block groups) 就对了!之前讲的都可以在这个区块内使用。 只是 inode 与 block
是动态产生,并非一开始于格式化就完成配置的。
o 文件系统活动登录区 (log section)
在登录区这个区域主要被用来纪录文件系统的变化,其实有点像是日志区!文件的变化会在这里纪录下来,直到该变化完整的写入到数据区后,该笔纪录才会被终结。如果文件系统因为某些缘故(例如最常见的停电)而损毁时,系统会拿这个登录区块来进行检验,看看系统挂掉之前,文件系统正在运作些啥动作,以快速的修复文件系统。
因为系统所有动作的时候都会在这个区块做个纪录,因此这个区块的磁盘活动是相当频繁的!xfs 设计在这个区域中,可以指定外部的磁盘来作为
xfs 文件系统的日志区块!例如,可以将 SSD 磁盘作为 xfs
的登录区,这样当系统需要进行任何活动时,就可以更快速的进行工作!
o 实时运作区 (realtime section)
当有文件要被建立时,xfs 会在这个区段里面找一个到数个的 extent 区块,将文件放置在这个区块内,等到分配完毕后,再写入到
data section 的 inode 与 block 去! 这个 extent 区块的大小得要在格式化的时候就先指定,最小值是
4K 最大可到 1G。一般非磁盘阵列的磁盘默认为 64K 容量,而具有类似磁盘阵列的 stripe 情况下,则建议 extent
设定为与 stripe 一样大较佳。这个extent 最好不要乱动,因为可能会影响到实体磁盘的效能。
 XFS 文件系统的描述数据观察
可以使用 xfs_info 去观察的! 详细的指令作法可以参考如下:
# xfs_info 挂载点|装置文件名
范例一:找出系统 /boot 这个挂载点底下的文件系统的 superblock 纪录
[root@study ~]# df -T /boot
Filesystem Type 1K-blocks Used Available Use% Mounted on
/dev/vda2 xfs 704 % /boot
# 没错!可以看得出来是 xfs 文件系统的!来观察一下内容吧!
# xfs_info /dev/vda2
1 meta-data=/dev/vda2 isize=256 agcount=4, agsize=65536 blks
2 = sectsz=512 attr=2, projid32bit=1
3 = crc=0 finobt=0
4 data = bsize=4096 blocks=262144, imaxpct=25
5 = sunit=0 swidth=0 blks
6 naming =version 2 bsize=4096 ascii-ci=0 ftype=0
7 log =internal bsize=4096 blocks=2560, version=2
8 = sectsz=512 sunit=0 blks, lazy-count=1
9 realtime =none extsz=4096 blocks=0, rtextents=0
上面的输出讯息可以这样解释:
 第 1 行里面的 isize 指的是 inode 的容量,每个有 256bytes 这么大。至于 agcount
则是前面谈到的储存区群组 (allocation group) 的个数,共有 4 个, agsize 则是指每个储存区群组具有
65536 个 block 。配合第 4 行的 block 设定为 4K,因此整个文件系统的容量应该就是 4*65536*4K
 第 2 行里面 sectsz 指的是逻辑扇区 (sector) 的容量设定为 512bytes 这么大的意思。
 第 4 行里面的 bsize 指的是 block 的容量,每个 block 为 4K 的意思,共有 262144 个 block
在这个文件系统内。
 第 5 行里面的 sunit 与 swidth 与磁盘阵列的 stripe
相关性较高。这部份我们底下格式化的时候会举一个例子来说明。
 第 7 行里面的 internal 指的是这个登录区的位置在文件系统内,而不是外部设备的意思。且占用了 4K * 2560 个
block,总共约 10M 的容量。
 第 9 行里面的 realtime 区域,里面的 extent 容量为 4K。不过目前没有使用。
由于我们并没有使用磁盘阵列,因此上头这个装置里头的 sunit 与 extent 就没有额外的指定特别的值。根据
xfs的说明,这两个值会影响到你的文件系统性能, 所以格式化的时候要特别留意!
文件系统的简单操作
稍微了解了文件系统后,再来我们得要知道如何查询整体文件系统的总容量与每个目录所占用的容量!此外,之前谈到的文件类型中尚未讲的很清楚的连结档
(Link file) 也会在后面介绍的。
磁盘与目录的容量
现在我们知道磁盘的整体数据是在 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 列出来!
[root@study ~]# df
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/mapper/centos-root
% /dev/shm
tmpfs 84 % /run
% /sys/fs/cgroup
/dev/mapper/centos-home 20 % /home
/dev/vda2 704 % /boot
# 在 Linux 底下如果 df
没有加任何选项,那么默认会将系统内所有的&(不含特殊内存内的文件系统与 swap) 都以 1
Kbytes 的容量来列出来!至于那个 /dev/shm 是与内存有关的挂载,先不要理他!
先来说明一下范例一所输出的结果讯息为:
 Filesystem:代表该文件系统是在哪个 partition ,所以列出装置名称;
 1k-blocks:说明底下的数字单位是 1KB!可利用 -h 或 -m 来改变容量;
 Used:使用掉的磁盘空间!
 Available:剩下的磁盘空间大小;
 Use%:就是磁盘的使用率!如果使用率高达 90% 以上时, 最好需要注意一下了,免得容量不足造成系统问题!(最容易被灌爆的
/var/spool/mail 这个放置邮件的磁盘)
 Mounted on:就是磁盘挂载的目录所在!(挂载点)
范例二:将容量结果以易读的容量格式显示出来
[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 M 884M 13% /boot
# 不同于范例一,这里会以 G/M 等容量格式显示出来,比较容易看!
范例三:将系统内的所有特殊文件格式及名称都列出来
[root@study ~]# df -aT
Filesystem Type 1K-blocks Used Available Use% Mounted on
rootfs rootfs
proc proc 0 0 0 - /proc
sysfs sysfs 0 0 0 - /sys
devtmpfs devtmpfs
securityfs securityfs 0 0 0 - /sys/kernel/security
tmpfs tmpfs
% /dev/shm
devpts devpts 0 0 0 - /dev/pts
tmpfs tmpfs 84 % /run
tmpfs tmpfs
% /sys/fs/cgroup
.....(中间省略).....
/dev/mapper/centos-root xfs
selinuxfs selinuxfs 0 0 0 - /sys/fs/selinux
.....(中间省略).....
/dev/mapper/centos-home xfs 20 % /home
/dev/vda2 xfs 704 % /boot
binfmt_misc binfmt_misc 0 0 0 - /proc/sys/fs/binfmt_misc
# 系统里面其实还有很多特殊的文件系统存在的。那些比较特殊的文件系统几乎都是在内存当中,例如 /proc
这个挂载点。因此,这些特殊的文件系统都不会占据磁盘空间
范例四:将 /etc 底下的可用的磁盘容量以易读的容量格式显示
[root@study ~]# df -h /etc
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/centos-root 10G 3.3G 6.8G 33% /
# 在 df 后面加上目录或者是文件时, df会自动的分析该目录或文件所在的 partition ,并将该 partition
的容量显示出来,所以就可以知道某个目录底下还有多少容量可以使用了
范例五:将目前各个 partition 当中可用的 inode 数量列出
[root@study ~]# df -ih
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/mapper/centos-root 10M 108K 9.9M 2% /
devtmpfs 154K 397 153K 1% /dev
tmpfs 156K 5 156K 1% /dev/shm
tmpfs 156K 497 156K 1% /run
tmpfs 156K 13 156K 1% /sys/fs/cgroup
# 这个范例则主要列出可用的 inode 剩余量与总容量。分析一下与范例一的关系,你可以清楚的发现到,通常 inode 的数量剩余都比
block 还要多
由于 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 列出容量显示;
范例一:列出目前目录下的所有文件容量
[root@study ~]# du
4 ./.cache/dconf &==每个目录都会列出来
4 ./.cache/abrt
8 ./.cache
....(中间省略)....
4 ./.ssh &==包括隐藏文件的目录
76 . &==这个目录(.)所占用的总量
# 直接输入 du 没有加任何选项时,则 du
会分析『目前所在目录』的文件与目录所占用的磁盘空间。但是,实际显示时,仅会显示目录容量(不含文件),因此 .
目录有很多文件没有被列出来,所以全部的目录相加不会等于 . 的容量!此外,输出的数值数据为 1K 大小的容量单位。
范例二:同范例一,但是将文件的容量也列出来
[root@study ~]# du -a
4 ./.bash_logout &==有文件的列表了
4 ./.bash_profile
4 ./.bashrc
....(中间省略)....
4 ./.ssh/known_hosts
范例三:检查根目录底下每个目录所占用的容量
[root@study ~]# du -sm /*
....(中间省略)....
du: cannot access ‘/proc/17772/task/17772/fd/4’: No such file or
du: cannot access ‘/proc/17772/fdinfo/4’: No such file or
0 /proc &==不会占用硬盘空间!
....(中间省略)....
3126 /usr &==系统初期最大就是他了啦!
# 这是个很常被使用的功能~利用通配符 *
来代表每个目录,如果想要检查某个目录下,哪个次目录占用最大的容量,可以用这个方法找出来。值得注意的是,如果刚刚安装好 Linux
时,那么整个系统容量最大的应该是 /usr 。而 /proc 虽然有列出容量,但是那个容量是在内存中,不占磁盘空间。至于 /proc
里头会列出一堆『No such file or
directory』的错误,别担心!因为是内存内的程序,程序执行结束就会消失,因此会有些目录找不到,是正确的!
与 df 不一样的是,du
这个指令其实会直接到文件系统内去搜寻所有的文件数据,所以上述第三个范例指令的运作会执行一小段时间!此外,在默认的情况下,容量的输出是以
KB 来设计的, 如果你想要知道目录占了多少 MB ,那么就使用 -m 这个参数即可!如果你只想要知道该目录占了多少容量的话,使用
-s 就可以!
至于 -S 这个选项部分,由于 du 默认会将所有文件的大小均列出,因此假设你在 /etc 底下使用 du 时, 所有的文件大小,包括
/etc 底下的次目录容量也会被计算一次。然后最终的容量 (/etc) 也会加总一次, 因此很多朋友都会误会 du
分析的结果不太对劲。所以啰,如果想要列出某目录下的全部数据, 或许也可以加上 -S 的选项,减少次目录的加总!
实体链接与符号链接: ln
在 Linux 底下的连结档有两种,一种是类似 Windows
的快捷方式功能的文件,可以让你快速的链接到目标文件(或目录);另一种则是透过文件系统的 inode
连结来产生新档名,而不是产生新文件!这种称为实体链接 (hard link)。
 Hard Link (实体链接, 硬式连结或实际连结)
在前一小节当中,我们知道几件重要的信息,包括:
 每个文件都会占用一个 inode ,文件内容由 inode 的记录来指向;
 想要读取该文件,必须要经过目录记录的文件名来指向到正确的 inode 号码才能读取。
也就是说,其实文件名只与目录有关,但是文件内容则与 inode 有关。
hard link 只是在某个目录下新增一笔档名链接到某 inode 号码的关连记录。
举个例子来说,假设我系统有个 /root/crontab 他是 /etc/crontab 的实体链接,也就是说这两个档名连结到同一个
inode , 自然这两个文件名的所有相关信息都会一模一样(除了文件名之外)。实际的情况可以如下所示:
# ll -i /etc/crontab
-rw-r--r--. 1 root root 451 Jun 10 2014 /etc/crontab
# ln /etc/crontab . &==建立实体链接的指令
[root@study ~]# ll -i /etc/crontab crontab
-rw-r--r--. 2 root root 451 Jun 10 2014 crontab
-rw-r--r--. 2 root root 451 Jun 10 2014 /etc/crontab
可以发现两个档名都连结到
这个 inode
号码,文件的权限/属性完全一样,因为这两个『档名』其实是一模一样的『文件』!第二个字段由原本的 1 变成 2
了!那个字段称为『连结』,这个字段的意义为:『有多少个档名链接到这个 inode 号码』的意思。
可以透过 1 或 2 的目录之 inode 指定的 block 找到两个不同的档名,而不管使用哪个档名均可以指到 real
那个 inode 去读取到最终数据!如果你将任何一个『档名』删除,其实 inode 与 block
都还是存在的!此时你可以透过另一个『档名』来读取到正确的文件数据!此外,不论你使用哪个『档名』来编辑,最终的结果都会写入到相同的
inode 与 block 中,因此均能进行数据的修改!
一般来说,使用 hard link 设定链接文件时,磁盘的空间与 inode 的数目都不会改变! hard link
只是在某个目录下的 block 多写入一个关连数据而已,既不会增加 inode 也不会耗用 block 数量!
!hard link 的制作中,其实还是可能会改变系统的 block 的,那就是当你新增这笔数据却刚好将目录的 block
填满时,就可能会新加一个 block 来记录文件名关连性,而导致磁盘空间的变化!不过,一般 hard link
所用掉的关连数据量很小,所以通常不会改变 inode 与磁盘空间的大小!
&hard link 是有限制的:
 不能跨 Filesystem;
 不能 link 目录。
因为如果使用 hard link 链接到目录时, 链接的数据需要连同被链接目录底下的所有数据都建立链接,举例来说,如果你要将 /etc
使用实体链接建立一个 /etc_hd 的目录时,那么在 /etc_hd 底下的所有档名同时都与 /etc 底下的檔名要建立 hard
link 的,而不是仅连结到 /etc_hd 与 /etc 而已。并且,未来如果需要在 /etc_hd
底下建立新文件时,连带的,/etc 底下的数据又得要建立一次 hard link ,因此造成环境相当大的复杂度。所以目前 hard
link 对于目录暂时还是不支持的!
 Symbolic Link (符号链接,亦即是快捷方式)
Symbolic link 就是在建立一个独立的文件,而这个文件会让数据的读取指向他 link
的那个文件的档名!由于只是利用文件来做为指向的动作, 所以,当来源档被删除之后,symbolic link
的文件会『开不了』,会一直说『无法开启某文件!』。实际上就是找不到原始『档名』!
举例来说,我们先建立一个符号链接文件链接到 /etc/crontab 去看看:
[root@study ~]# ln -s /etc/crontab crontab2
[root@study ~]# ll -i /etc/crontab /root/crontab2
-rw-r--r--. 2 root root 451 Jun 10 2014 /etc/crontab
lrwxrwxrwx. 1 root root 12 Jun 23 22:31 /root/crontab2
-& /etc/crontab
由上表的结果我们可以知道两个文件指向不同的 inode
号码,当然就是两个独立的文件存在!而且连结档的重要内容就是他会写上目标文件的『文件名』,你可以发现为什么上表中连结档的大小为 12
bytes 呢?因为箭头(--&)右边的档名『/etc/crontab』总共有 12 个英文,每个英文占用 1 个 bytes
,所以文件大小就是 12bytes 了!
由 1 号 inode 读取到连结档的内容仅有档名,根据档名链接到正确的目录去取得目标文件的 inode
,最终就能够读取到正确的数据了。可以发现的是,如果目标文件(/etc/crontab)被删除了,那么整个环节就会无法继续进行下去,所以就会发生无法透过连结档读取的问题了!
这里还是得特别留意,这个 Symbolic Link 与 Windows 的快捷方式可以给他划上等号,由 Symbolic link
所建立的文件为一个独立的新的文件,所以会占用掉 inode 与 block !
由上面的说明来看,似乎 hard link
比较安全,因为即使某一个目录下的关连数据被杀掉了,也没有关系,只要有任何一个目录下存在着关连数据,那么该文件就不会不见!举上面的例子来说,我的/etc/crontab
与 /root/crontab 指向同一个文件,如果我删除了 /etc/crontab 这个文件,该删除的动作其实只是将 /etc
目录下关于 crontab 的关连数据拿掉而已, crontab 所在的 inode 与 block 其实都没有被变动!
不过由于 Hard Link 的限制太多了,包括无法做『目录』的 link , 所以在用途上面是比较受限的!反而是 Symbolic
Link 的使用方面较广!
# 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 - df -i .
6602 . &==先注意一下这里的容量是多少!
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/mapper/centos-root 748 % /
# 利用 du 与 df 来检查一下目前的参数~那个 du -sb 是计算整个 /tmp 底下有多少 bytes 的容量!
范例二:将 /tmp/passwd 制作 hard link 成为 passwd-hd 文件,并观察文件与容量
[root@study tmp]# ln passwd passwd-hd
[root@study tmp]# du - df -i .
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/mapper/centos-root 748 % /
# 仔细看,即使多了一个文件在 /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-so 指向的 inode number 不同了!这是一个新的文件~这个文件的内容是指向passwd
的。passwd-so 的大小是 6bytes ,因为 『passwd』 这个单字共有六个字符之故
[root@study tmp]# du - df -i .
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/mapper/centos-root 749 % /
# 整个容量与 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
# 符号链接无法开启!另外,如果符号链接的目标文件不存在,档名的部分就会有特殊的颜色显示!
使用 ln 如果不加任何参数的话,那么就是 Hard Link!如同范例二的情况,增加了 hard link 之后,可以发现使用
ls -l 时,显示的 link 那一栏属性增加了!而如果这个时候砍掉 passwd ,passwd-hd的内容还是会跟原来
passwd 相同,但是 passwd-so 就会找不到该文件了!
而如果 ln 使用 -s 的参数时,就做成差不多是 Windows 底下的『快捷方式』的意思。当你修改 Linux 下的
symbolic link
文件时,则更动的其实是『原始档』,所以不论你的这个原始档被连结到哪里去,只要你修改了连结档,原始档就跟着变! 以上面为例,由于你使用
-s 的参数建立一个名为passwd-so 的文件,则你修改 passwd-so 时,其内容与 passwd
完全相同,并且,当你按下储存之后,被改变的将是 passwd 这个文件!
此外,如果你做了底下这样的连结:
ln -s /bin /root/bin
那么如果你进入 /root/bin 这个目录下,『该目录其实是 /bin 这个目录,因为你做了连结
档了!』所以,如果你进入 /root/bin 这个刚刚建立的链接目录, 并且将其中的数据杀掉时, /bin
里面的数据就通通不见了!这点请千万注意!
 关于目录的 link 数量:
当我们以 hard link 进行『文件的连结』时,可以发现,在 ls -l 所显
示的第二字段会增加一才对,一个『空目录』里面至少会存在 . 与 .. 这两个目录! 那么,当我们建立一个新目录名称为
/tmp/testing 时,基本上会有三个东西,那就是:
 /tmp/testing
 /tmp/testing/.
 /tmp/testing/..
而其中 /tmp/testing 与 /tmp/testing/. 其实是一样的!都代表该目录啊,而 /tmp/testing/..
则代表 /tmp 这个目录,所以说,当我们建立一个新的目录时, 『新的目录的 link 数为 2 ,而上层目录的 link 数则会增加
[root@study ~]# ls -ld /tmp
drwxrwxrwt. 14 root root 4096 Jun 23 22:42 /tmp
[root@study ~]# mkdir /tmp/testing1
[root@study ~]# ls -ld /tmp
drwxrwxrwt. 15 root root 4096 Jun 23 22:45 /tmp # 这里的 link 数量加 1
[root@study ~]# ls -ld /tmp/testing1
&drwxr-xr-x. 2 root root 6 Jun 23 22:45
/tmp/testing1/
原本的所谓上层目录 /tmp 的 link 数量由 14 增加为 15 ,至于新目录 /tmp/testing 则为 2
磁盘的分区、格式化、检验与挂载
对于一个系统管理者( root )而言,磁盘的的管理是相当重要的一环,尤其近来磁盘已经渐渐的被当成是消耗品了 .....
如果我们想要在系统里面新增一颗磁盘时,应该有哪些动作需要做的呢:
1. 对磁盘进行分区,以建立可用的 partition ;
2. 对该 partition 进行格式化 (format),以建立系统可用的 filesystem;
3. 若想要仔细一点,则可对刚刚建立好的 filesystem 进行检验;
4. 在 Linux 系统上,需要建立挂载点 (亦即是目录),并将他挂载上来;
在上述的过程当中,还有很多需要考虑的,例如磁盘分区槽 (partition) 需要定多大? 是否需要加入 journal
的功能?inode 与 block 的数量应该如何规划等等的问题。但是这些问题的决定,都需要与你的主机用途来加以考虑的。
观察磁盘分区状态
由于目前磁盘分区主要有 MBR 以及 GPT 两种格式,这两种格式所使用的分区工具不太一样!你当然可以使用本章预计最后才介绍的
parted 这个通通有支持的工具来处理,不过,我们还是比较习惯使用 fdisk 或者是 gdisk
来处理分区!因此,我们自然就得要去找一下目前系统有的磁盘有哪些?这些磁盘是 MBR 还是 GPT 等等的!这样才能处理!
 lsblk 列出系统上的所有磁盘列表
lsblk 可以看成『 list block device 』的缩写,就是列出所有储存装置的意思!这个工具软件真的很好用
# lsblk [-dfimpt] [device]
-d :仅列出磁盘本身,并不会列出该磁盘的分区数据
-f :同时列出该磁盘内的文件系统名称
-i :使用 ASCII 的线段输出,不要使用复杂的编码 (再某些环境下很有用)
-m :同时输出该装置在 /dev 底下的权限数据 (rwx 的数据)
-p :列出该装置的完整文件名!而不是仅列出最后的名字而已。
-t :列出该磁盘装置的详细数据,包括磁盘队列机制、预读写的数据量大小等
范例一:列出本系统下的所有磁盘与磁盘内的分区信息
[root@study ~]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sr0 11:0 1 1024M 0 rom
vda 252:0 0 40G 0 disk # 一整颗磁盘
|-vda1 252:1 0 2M 0 part
|-vda2 252:2 0 1G 0 part /boot
`-vda3 252:3 0 30G 0 part
&|-centos-root 253:0 0 10G 0 lvm / # 在 vda3
内的其他文件系统
&|-centos-swap 253:1 0 1G 0 lvm [SWAP]
&`-centos-home 253:2 0 5G 0 lvm /home
从上面的输出我们可以很清楚的看到,目前的系统主要有个 sr0 以及一个 vda 的装置,而 vda 的
装置底下又有三个分区, 其中 vda3 甚至还有因为 LVM 产生的文件系统!相当的完整吧!从范例
一我们来谈谈默认输出的信息有哪些。
 NAME:就是装置的文件名啰!会省略 /dev 等前导目录!
 MAJ:MIN:其实核心认识的装置都是透过这两个代码来熟悉的!分别是主要:次要装置代码!
 RM:是否为可卸除装置 (removable device),如光盘、USB 磁盘等等
 SIZE:当然就是容量啰!
 RO:是否为只读装置的意思
 TYPE:是磁盘 (disk)、分区槽 (partition) 还是只读存储器 (rom) 等输出
 MOUTPOINT:就是前一章谈到的挂载点!
范例二:仅列出 /dev/vda 装置内的所有数据的完整文件名
[root@study ~]# lsblk -ip /dev/vda
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
/dev/vda 252:0 0 40G 0 disk
|-/dev/vda1 252:1 0 2M 0 part
|-/dev/vda2 252:2 0 1G 0 part /boot
`-/dev/vda3 252:3 0 30G 0 part
&|-/dev/mapper/centos-root 253:0 0 10G 0 lvm
&|-/dev/mapper/centos-swap 253:1 0 1G 0 lvm
&`-/dev/mapper/centos-home 253:2 0 5G 0 lvm /home
# 完整的檔名,由 / 开始写
 blkid 列出装置的 UUID 等参数
虽然 lsblk 已经可以使用 -f 来列出文件系统与装置的 UUID 数据,UUID 是全局单一标识符 (universally
unique identifier),Linux
会将系统内所有的装置都给予一个独一无二的标识符,这个标识符就可以拿来作为挂载或者是使用这个装置/文件系统之用了。
[root@study ~]# blkid
/dev/vda2: UUID="94ac5f77-cb8a-495e-a65b-2efc"
TYPE="xfs"
/dev/vda3: UUID="WStYq1-P93d-oShM-JNe3-KeDl-bBf6-RSmfae"
TYPE="LVM2_member"
/dev/sda1: UUID="35BC-6D6B" TYPE="vfat"
/dev/mapper/centos-root:
UUID="299bdc5b-de6d-486a-a0d2-375402aaab27" TYPE="xfs"
/dev/mapper/centos-swap:
UUID="905dc471-6c10--a802edbd862d" TYPE="swap"
/dev/mapper/centos-home:
UUID="2a28-48e0-be4a-6" TYPE="xfs"
如上所示,每一行代表一个文件系统,主要列出装置名称、UUID 名称以及文件系统的类型 (TYPE)!
 parted 列出磁盘的分区表类型与分区信息
虽然我们已经知道了系统上面的所有装置,并且透过 blkid
也知道了所有的文件系统!不过,还是不清楚磁盘的分区类型。这时我们可以透过简单的 parted
来输出!我们这里仅简单的利用他的输出而已
# parted device_name print
范例一:列出 /dev/vda 磁盘的相关数据
[root@study ~]# parted /dev/vda print
Model: Virtio Block Device (virtblk) # 磁盘的模块名称(厂商)
Disk /dev/vda: 42.9GB # 磁盘的总容量
Sector size (logical/physical): 512B/512B # 磁盘的每个逻辑/物理扇区容量
Partition Table: gpt # 分区表的格式 (MBR/GPT)
Disk Flags: pmbr_boot
Number Start End Size File system Name Flags # 底下才是分区数据
1 1049kB 3146kB 2097kB bios_grub
2 3146kB 1077MB 1074MB xfs
3 1077MB 33.3GB 32.2GB lvm
我们用的就是 GPT 的分区格式
&&& 磁盘分区:
gdisk/fdisk
要注意的是:『MBR 分区表请使用 fdisk 分区, GPT 分区表请使用 gdisk
分区!』这个不要搞错~否则会分区失败的!另外,这两个工具软件的操作很类似,执行了该软件后,可以透过该软件内部的说明数据来操作,因此不需要硬背!只要知道方法即可。
 gdisk
# gdisk 装置名称
范例:由前一小节的 lsblk 输出,我们知道系统有个 /dev/vda,请观察该磁盘的分区与相关数据
[root@study ~]# gdisk /dev/vda &==仔细看,不要加上数字!
GPT fdisk (gdisk) version 0.8.6
Partition table scan:
&MBR: protective
&BSD: not present
&APM: not present
&GPT: present
Found valid GPT with protective MBR; using GPT. &==找到了 GPT
的分区表!
Command (? for help): &==这里可以让你输入指令动作,可以按问号 (?) 来查看可用指令
Command (? for help): ?
b back up GPT data to a file
c change a partition's name
d delete a partition # 删除一个分区
i show detailed information on a partition
l list known partition types
n add a new partition # 增加一个分区
o create a new empty GUID partition table (GPT)
p print the partition table # 印出分区表 (常用)
q quit without saving changes # 不储存分区就直接离开 gdisk
r recovery and transformation options (experts only)
s sort partitions
t change a partition's type code
v verify disk
w write table to disk and exit # 储存分区操作后离开 gdisk
x extra functionality (experts only)
? print this menu
Command (? for help):
你应该要透过 lsblk 或 blkid 先找到磁盘,再用 parted /dev/xxx print
来找出内部的分区表类型,之后才用 gdisk 或 fdisk 来操作系统。 上表中可以发现 gdisk 会扫描 MBR 与 GPT
分区表,不过这个软件还是单纯使用在 GPT 分区表比较好!
其中比较不一样的是『q 与 w』! 不管你进行了什么动作,只要离开 gdisk 时按下『q』,那么所有的
动作『都不会生效!』相反的, 按下『w』就是动作生效的意思。
Command (? for help): p &== 这里可以输出目前磁盘的状态
Disk /dev/vda:
sectors, 40.0 GiB # 磁盘文件名/扇区数与总容量
Logical sector size: 512 bytes # 单一扇区大小为 512 bytes
Disk identifier (GUID): A4C3C813-62AF-4BFE-BAC9-112EBD87A483 # 磁盘的
GPT 标识符
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is
Partitions will be aligned on 2048-sector boundaries
Total free space is
sectors (9.0 GiB)
Number Start (sector) End (sector) Size Code Name #
底下为完整的分区信息了!
&1 .0 MiB EF02 # 第一个分区槽数据
1024.0 MiB 0700
# 分区编号 开始扇区号码 结束扇区号码 容量大小
Command (? for help): q
# 想要不储存离开吗?按下 q 就对了!不要随便按 w !
使用『 p 』可以列出目前这颗磁盘的分区表信息,这个信息的上半部在显示整体磁盘的状态。这个磁盘共有 40GB 左右的容量,共有
个扇区,每个扇区的容量为512bytes。 要注意的是,现在的分区主要是以扇区为最小的单位!
下半部的分区表信息主要在列出每个分区槽的个别信息项目。每个项目的意义为:
 Number:分区槽编号,1 号指的是 /dev/vda1 这样计算。
 Start (sector):每一个分区槽的开始扇区号码位置
 End (sector):每一个分区的结束扇区号码位置,与 start 之间可以算出分区槽的总容量
 Size:就是分区槽的容量了
 Code:在分区槽内的可能的文件系统类型。Linux 为 8300,swap 为
8200。不过这个项目只是一个提示而已,不见得真的代表此分区槽内的文件系统!
 Name:文件系统的名称等等。
从上表我们可以发现几件事情:
 整部磁盘还可以进行额外的分区,因为最大扇区为 ,但只使用到
 分区槽的设计中,新分区通常选用上一个分区的结束扇区号码数加 1 作为起始扇区号码!
这个 gdisk 只有 root 才能执行,此外,请注意,使用的『装置文件名』请不要加上数字,因为 partition
是针对『整个磁盘装置』而不是某个 partition 呢!所以执行『 gdisk /dev/vda1 』 就会发生错误!要使用
gdisk /dev/vda 才对!
 用 gdisk 新增分区槽
经过上面的观察,我们也确认系统还有剩下的容量可以来操作练习分区! 假设我需要有如下的分区需求:
 1GB 的 xfs 文件系统 (Linux)
 1GB 的 vfat 文件系统 (Windows)
&#6GB 的 swap (Linux swap)(这个分区等一下会被删除!)
那就来处理处理!
[root@study ~]# gdisk /dev/vda
Command (? for help): p
Number Start (sector) End (sector) Size Code Name
&1 .0 MiB EF02
1024.0 MiB 0700
# 找出最后一个 sector 的号码是很重要的!
Command (? for help): ? # 查一下增加分区的指令为何
Command (? for help): n # 就是这个!所以开始新增的行为!
Partition number (4-128, default 4): 4 # 预设就是 4 号,所以也能 enter
First sector (34-, default = ) or {+-}size{KMGTP}:
# 也能 enter
Last sector (86046, default = ) or
{+-}size{KMGTP}: +1G # 决不要 enter
# 我们不需要自己去计算扇区号码,透过 +容量 的这个方式,就可以让 gdisk
主动去帮你算出最接近你需要的容量的扇区号码!
Current type is 'Linux filesystem'
Hex code or GUID (L to show codes, Enter = 8300): # 使用默认值即可~直接
enter 下去!
# 这里在让你选择未来这个分区槽预计使用的文件系统!预设都是 Linux 文件系统的 8300 啰!
Command (? for help): p
Number Start (sector) End (sector) Size Code Name
&1 .0 MiB EF02
1024.0 MiB 0700
&4 .0 MiB 8300 Linux
filesystem
重点在『 Last sector
』那一行,那行绝对不要使用默认值!因为默认值会将所有的容量用光!因此它默认选择最大的扇区号码!因为我们仅要 1GB
而已,所以你得要加上 +1G 这样即可!不需要计算 sector 的数量,gdisk
会根据你填写的数值,直接计算出最接近该容量的扇区数!每次新增完毕后,请立即『 p
』查看一下结果!请继续处理后续的两个分区槽!最终出现的画面会有点像底下这样才对!
Command (? for help): p
Number Start (sector) End (sector) Size Code Name
&1 .0 MiB EF02
1024.0 MiB 0700
&4 .0 MiB 8300 Linux
filesystem
&5 .0 MiB 0700 Microsoft
basic data
MiB 8200 Linux
基本上,几乎都用默认值,然后透过 +1G, +500M 来建置所需要的另外两个分区槽!比较有趣的是文件系统的 ID !一般来说,
Linux 大概都是 e00 等三种格式, Windows 几乎都用0700 这样,如果忘记这些数字,可以在
gdisk 内按下:『 L 』来显示! 如果一切的分区状态都正常的话,那么就直接写入磁盘分区表吧!
Command (? for help): w
Final checks complete. About to write GPT data. THIS WILL OVERWRITE
PARTITIONS!!
Do you want to proceed? (Y/N): y
OK; writing new GUID partition table (GPT) to /dev/vda.
Warning: The kernel is still using the old partition table.
The new table will be used at the next reboot.
The operation has completed successfully.
# gdisk 会先警告你可能的问题,我们确定分区是对的,这时才按下 y
!不过怎么还有警告?这是因为这颗磁盘目前正在使用当中,因此系统无法立即加载新的分区表~
[root@study ~]# cat /proc/partitions
major minor #blocks name
252 1 2048 vda1
252 2 1048576 vda2
253 1 1048576 dm-1
253 2 5242880 dm-2
# 你可以发现,并没有 vda4, vda5, vda6 喔!因为核心还没有更新!
因为 Linux
此时还在使用这颗磁盘,为了担心系统出问题,所以分区表并没有被更新!这个时候我们有两个方式可以来处理!其中一个是重新启动,另外一个则是透过
partprobe 这个指令来处理
 partprobe 更新 Linux 核心的分区表信息
# partprobe [-s] # 你可以不要加 -s !那么屏幕不会出现讯息!
[root@study ~]# partprobe -s # 不过还是建议加上 -s 比较清晰!
/dev/vda: gpt partitions 1 2 3 4 5 6
[root@study ~]# lsblk /dev/vda # 实际的磁盘分区状态
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
vda 252:0 0 40G 0 disk
|-vda1 252:1 0 2M 0 part
|-vda2 252:2 0 1G 0 part /boot
|-vda3 252:3 0 30G 0 part
| |-centos-root 253:0 0 10G 0 lvm /
| |-centos-swap 253:1 0 1G 0 lvm [SWAP]
| `-centos-home 253:2 0 5G 0 lvm /home
|-vda4 252:4 0 1G 0 part
|-vda5 252:5 0 1G 0 part
`-vda6 252:6 0 500M 0 part
[root@study ~]# cat /proc/partitions # 核心的分区纪录
major minor #blocks name
252 1 2048 vda1
252 2 1048576 vda2
252 4 1048576 vda4
252 5 1048576 vda5
252 6 512000 vda6
# 现在核心也正确的抓到了分区参数了!
 用 gdisk 删除一个分区槽
[root@study ~]# gdisk /dev/vda
Command (? for help): p
Number Start (sector) End (sector) Size Code Name
&1 .0 MiB EF02
1024.0 MiB 0700
&4 .0 MiB 8300 Linux
filesystem
&5 .0 MiB 0700 Microsoft
basic data
MiB 8200 Linux
Command (? for help): d
Partition number (1-6): 6
Command (? for help): p
# 发现 /dev/vda6 不见了
Command (? for help): w
[root@study ~]# lsblk
[root@study ~]# partprobe -s
[root@study ~]# lsblk
# 这个时候, /dev/vda6 才消失不见了
Tips 万分注意!不要去处理一个正在使用中的分区槽
 fdisk
因为 fdisk 跟 gdisk 使用的方式几乎一样!此外,fdisk 有时会使用磁柱 (cylinder) 作为分区的最小单位,与
gdisk 默认使用sector 不太一样!大致上只是这点差别!另外,MBR 分区是有限制的 (Primary, Extended,
Logical...)!里仅列出相关的指令给大家对照参考!
[root@study ~]# fdisk /dev/sda
Command (m for help): m &== 输入 m 后,就会看到底下这些指令介绍
Command action
&a toggle a bootable flag
&b edit bsd disklabel
&c toggle the dos compatibility flag
&d delete a partition &==删除一个 partition
&l list known partition types
&m print this menu
&n add a new partition &==新增一个 partition
&o create a new empty DOS partition table
&p print the partition table &==在屏幕上显示分区表
&q quit without saving changes &==不储存离开 fdisk
&s create a new empty Sun disklabel
&t change a partition's system id
&u change display/entry units
&v verify the partition table
&w write table to disk and exit
&==将刚刚的动作写入分区表
&x extra functionality (experts only)
磁盘格式化(建置文件系统)
分区完毕后自然就是要进行文件系统的格式化!格式化的指令非常的简单,那就是『make filesystem,
mkfs』这个指令!这个指令其实是个综合的指令,他会去呼叫正确的文件系统格式化工具软件!因为 CentOS 7 使用 xfs
作为预设文件系统,底下我们会先介绍 mkfs.xfs ,之后介绍新一代的 EXT 家族成员 mkfs.ext4,最后再聊一聊 mkfs
这个综合指令!
 XFS 文件系统 mkfs.xfs
我们常听到的『格式化』其实应该称为『建置文件系统 (make filesystem)』才对!所以使用的指令是
mkfs!那我们要建立的其实是 xfs 文件系统, 因此使用的是 mkfs.xfs 这个指令才对。这个指令是这样使用的:
# mkfs.xfs [-b bsize] [-d parms] [-i parms] [-l parms] [-L label]
[-f] [-r parms] 装置名称
关于单位:底下只要谈到『数值』时,没有加单位则为 bytes 值,可以用 k,m,g,t,p (小写)等来解释比较特殊的是 s
这个单位,它指的是 sector 的『个数』!
-b :后面接的是 block 容量,可由 512 到 64k,不过最大容量限制为 Linux 的 4k !
-d :后面接的是重要的 data section 的相关参数值,主要的值有:
&agcount=数值 :设定需要几个储存群组的意思(AG),通常与 CPU 有关
&agsize=数值 :每个 AG 设定为多少容量的意思,通常 agcount/agsize
只选一个设定即可
&file :指的是『格式化的装置是个文件而不是个装置』的意思!(例如虚拟磁盘)
&size=数值 :data section
的容量,亦即你可以不将全部的装置容量用完的意思
&su=数值 :当有 RAID 时,那个 stripe 数值的意思,与底下的 sw
&sw=数值 :当有 RAID 时,用于储存数据的磁盘数量(须扣除备份碟与备用碟)
&sunit=数值 :与 su 相当,不过单位使用的是『几个 sector(512bytes
大小)』的意思
&swidth=数值 :就是 su*sw 的数值,但是以『几个 sector(512bytes
大小)』来设定
-f :如果装置内已经有文件系统,则需要使用这个 -f 来强制格式化才行!
-i :与 inode 有较相关的设定,主要的设定值有:
&size=数值 :最小是 256bytes 最大是 2k,一般保留 256
就足够使用了!
&internal=[0|1]:log 装置是否为内建?预设为 1
内建,如果要用外部装置,使用底下设定
&logdev=device :log 装置为后面接的那个装置上头的意思,需设定
internal=0 才可!
&size=数值 :指定这块登录区的容量,通常最小得要有 512 个 block,大约 2M
以上才行!
-L :后面接这个文件系统的标头名称 Label name 的意思!
-r :指定 realtime section 的相关设定值,常见的有:
&extsize=数值 :就是那个重要的 extent 数值,一般不须设定,但有 RAID
&最好设定与 swidth 的数值相同较佳!最小为 4K 最大为 1G 。
范例:将前一小节分区出来的 /dev/vda4 格式化为 xfs 文件系统
[root@study ~]# mkfs.xfs /dev/vda4
meta-data=/dev/vda4 isize=256 agcount=4, agsize=65536 blks
&= sectsz=512 attr=2, projid32bit=1
&= crc=0 finobt=0
data = bsize=4096 blocks=262144, imaxpct=25
&= sunit=0 swidth=0 blks
naming =version 2 bsize=4096 ascii-ci=0 ftype=0
log =internal log bsize=4096 blocks=2560, version=2
&= sectsz=512 sunit=0 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
# 很快格是化完毕!都用默认值!较重要的是 inode 与 block 的数值
[root@study ~]# blkid /dev/vda4
/dev/vda4: UUID="7b-4dfd-a015-c"
TYPE="xfs"
# 确定建置好 xfs 文件系统了!
使用默认的 xfs 文件系统参数来建置系统即可!速度非常快!如果我们有其他额外想要处理的项目,
才需要加上一堆设定值!举例来说,因为 xfs 可以使用多个数据流来读写系统,以增加速度,因此
那个 agcount 可以跟 CPU 的核心数来做搭配!举例来说,如果我的服务器仅有一颗 4 核心,但是
有启动 Intel 超线程功能,则系统会仿真出 8 颗 CPU 时,那个 agcount 就可以设定为 8 喔!举个
例子来瞧瞧:
范例:找出你系统的 CPU 数,并据以设定你的 agcount 数值
[root@study ~]# grep 'processor' /proc/cpuinfo
processor : 0
ww file :指的是『格式化的装置是个文件而不是个装置』的意思!(例如虚拟磁盘)
&size=数值 :data section
的容量,亦即你可以不将全部的装置容量用完的意思
&su=数值 :当有 RAID 时,那个 stripe 数值的意思,与底下的 sw
&sw=数值 :当有 RAID 时,用于储存数据的磁盘数量(须扣除备份碟与备用碟)
&sunit=数值 :与 su 相当,不过单位使用的是『几个 sector(512bytes
大小)』的意思
&swidth=数值 :就是 su*sw 的数值,但是以『几个 sector(512bytes
大小)』来设定
-f :如果装置内已经有文件系统,则需要使用这个 -f 来强制格式化才行!
-i :与 inode 有较相关的设定,主要的设定值有:
&size=数值 :最小是 256bytes 最大是 2k,一般保留 256
就足够使用了!
&internal=[0|1]:log 装置是否为内建?预设为 1
内建,如果要用外部装置,使用底下设定
&logdev=device :log 装置为后面接的那个装置上头的意思,需设定
internal=0 才可!
&size=数值 :指定这块登录区的容量,通常最小得要有 512 个 block,大约 2M
以上才行!
-L :后面接这个文件系统的标头名称 Label name 的意思!
-r :指定 realtime section 的相关设定值,常见的有:
&extsize=数值 :就是那个重要的 extent 数值,一般不须设定,但有 RAID
&最好设定与 swidth 的数值相同较佳!最小为 4K 最大为 1G 。
范例:将前一小节分区出来的 /dev/vda4 格式化为 xfs 文件系统
[root@study ~]# mkfs.xfs /dev/vda4
meta-data=/dev/vda4 isize=256 agcount=4, agsize=65536 blks
&= sectsz=512 attr=2, projid32bit=1
&= crc=0 finobt=0
data = bsize=4096 blocks=262144, imaxpct=25
&= sunit=0 swidth=0 blks
naming =version 2 bsize=4096 ascii-ci=0 ftype=0
log =internal log bsize=4096 blocks=2560, version=2
&= sectsz=512 sunit=0 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
# 很快格是化完毕!都用默认值!较重要的是 inode 与 block 的数值
[root@study ~]# blkid /dev/vda4
/dev/vda4: UUID="7b-4dfd-a015-c"
TYPE="xfs"
# 确定建置好 xfs 文件系统了!
使用默认的 xfs 文件系统参数来建置系统即可!速度非常快!如果我们有其他额外想要处理的项目,才需要加上一堆设定值!举例来说,因为
xfs 可以使用多个数据流来读写系统,以增加速度,因此那个 agcount 可以跟 CPU
的核心数来做搭配!举例来说,如果我的服务器仅有一颗 4 核心,但是有启动 Intel 超线程功能,则系统会仿真出 8 颗 CPU
时,那个 agcount 就可以设定为 8 !
范例:找出你系统的 CPU 数,并据以设定你的 agcount 数值
[root@study ~]# grep 'processor' /proc/cpuinfo
processor : 0
processor : 1
# 所以就是有两颗 CPU 的意思,那就来设定设定我们的 xfs 文件系统格式化参数吧!!
[root@study ~]# mkfs.xfs -f -d agcount=2 /dev/vda4
meta-data=/dev/vda4 isize=256 agcount=2, agsize=131072 blks
&= sectsz=512 attr=2, projid32bit=1
&= crc=0 finobt=0
.....(底下省略).....
# 可以跟前一个范例对照看看,可以发现 agcount 变成 2 了!此外,因为已经格式化过一次,因此 mkfs.xfs
可能会出现不给你格式化的警告!因此需要使用 -f
 XFS 文件系统 for RAID 效能优化 (Optional)
磁盘阵列是多颗磁盘组成一颗大磁盘的意思,利用同步写入到这些磁盘的技术,不但可以加快读写速度,还可以让某一颗磁盘坏掉时,整个文件系统还是可以持续运作的状态!那就是所谓的容错。
基本上,磁盘阵列 (RAID) 就是透过将文件先细分为数个小型的分区区块 (stripe) 之后,然后将众多的 stripes
分别放到磁盘阵列里面的所有磁盘,所以一个文件是被同时写入到多个磁盘去,当然效能会好一些。为了文件的保全性,所以在这些磁盘里面,会保留数个
(与磁盘阵列的规划有关) 备份磁盘 (parity disk), 以及可能会保留一个以上的备用磁盘 (spare
disk),这些区块基本上会占用掉磁盘阵列的总容量,不过对于数据的保全会比较有保障!
那个分区区块 stripe 的数值大多介于 4K 到 1M 之间,这与你的磁盘阵列卡支持的项目有关。stripe
与你的文件数据容量以及效能相关性较高。 当你的系统大多是大型文件时,一般建议 stripe
可以设定大一些,这样磁盘阵列读/写的频率会降低,效能会提升。如果是用于系统, 那么小文件比较多的情况下, stripe 建议大约在
64K 左右可能会有较佳的效能。不过,还是都须要经过测试!更多详细的磁盘阵列。
文件系统的读写要能够有优化,最好能够搭配磁盘阵列的参数来设计,这样效能才能够起来!也就是说,你可以先在文件系统就将 stripe
规划好, 那交给 RAID 去存取时,它就无须重复进行文件的stripe 过程,效能当然会更好!假设个环境:
 我有两个线程的 CPU 数量,所以 agcount 最好指定为 2
 当初设定 RAID 的 stripe 指定为 256K 这么大,因此 su 最好设定为 256k
 设定的磁盘阵列有 8 颗,因为是 RAID5 的设定,所以有一个 parity (备份碟),因此指定 sw 为 7
 由上述的数据中,我们可以发现数据宽度 (swidth) 应该就是 256K*7 得到 1792K,可以指定 extsize
这里仅快速的使用 mkfs.xfs 的参数来处理格式化的动作
[root@study ~]# mkfs.xfs -f -d agcount=2,su=256k,sw=7 -r
extsize=1792k /dev/vda4
meta-data=/dev/vda4 isize=256 agcount=2, agsize=131072 blks
&= sectsz=512 attr=2, projid32bit=1
&= crc=0 finobt=0
data = bsize=4096 blocks=262144, imaxpct=25
&= sunit=64 swidth=448 blks
naming =version 2 bsize=4096 ascii-ci=0 ftype=0
log =internal log bsize=4096 blocks=2560, version=2
&= sectsz=512 sunit=64 blks, lazy-count=1
realtime =none extsz=1835008 blocks=0, rtextents=0
从输出的结果来看, agcount 没啥问题, sunit 结果是 64 个 block,因为每个 block 为
4K,所以算出来容量就是 256K 也没错! 那个 swidth 也相同!使用 448 * 4K 得到 1792K!那个 extsz
则是算成 bytes 的单位,换算结果也没错!上面是个方式,那如果使用 sunit 与 swidth 直接套用在mkfs.xfs
当中呢?那你得小心了!因为指令中的这两个参数用的是『几个 512bytes 的 sector
数量』的意思!是『数量』单位而不是『容量』单位!因此先计算为:
 sunit = 256K/512byte*1024(bytes/K) = 512 个 sector
 swidth = 7 个磁盘 * sunit = 7 * 512 = 3584 个 sector
所以指令

我要回帖

更多关于 linux 查看文件系统 的文章

 

随机推荐