基础命令学习目录首页
档案系统特性
传统的磁盘与档案系统之应用中, 一个分割槽就是只能够被格式化成为一个档案系统, 所以我们可以说一个 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 都有编号, 而每个档案都会占用一个 inode ,inode 内则有档案资料放置的 block 号码. 因此, 我们可以知道的是, 如果能够找到档案的 inode 的话, 那么自然就会知道这个档案所放置资料的 block 号码, 当然也就能够读出该档案的实际资料了. 这是个比较有效率的作法, 因为如此一来我们的磁盘就能够在短时间内读取出全部的资料, 读写的效能比较好啰.
我们将 inode 与 block 区块用图解来说明一下, 如下图所示, 档案系统先格式化出 inode 与 block 的区块, 假设某一个档案的属性与权限资料是放置到 inode 4 号(下图较小方格内), 而这个 inode 记录了档案资料的实际放置点为 2, 7, 13, 15 这四个 block 号码, 此时我们的作业系统就能够据此来排列磁盘的读取顺序, 可以一口气将四个 block 内容读出来! 那么资料的读取就如同下图中的箭头所指定的模样了.
这种资料存取的方法我们称为索引式档案系统(indexed allocation). 那有没有其他的惯用档案系统可以比较一下啊? 有的, 那就是我们惯用的 U 盘(快闪记忆体),U 盘使用的档案系统一般为 FAT 格式. FAT 这种格式的档案系统并没有 inode 存在, 所以 FAT 没有办法将这个档案的所有 block 在一开始就读取出来. 每个 block 号码都记录在前一个 block 当中, 他的读取方式有点像底下这样:
上图中我们假设档案的资料依序写入 1->7->4->15 号这四个 block 号码中, 但这个档案系统没有办法一口气就知道四个 block 的号码, 他得要一个一个的将 block 读出后, 才会知道下一个 block 在何处. 如果同一个档案资料写入的 block 分散的太过厉害时, 则我们的磁盘读取头将无法在磁盘转一圈就读到所有的资料, 因此磁盘就会多转好几圈才能完整的读取到这个档案的内容!
常常会听到所谓的『碎片整理』吧? 需要碎片整理的原因就是档案写入的 block 太过于离散了, 此时档案读取的效能将会变的很差所致. 这个时候可以透过碎片整理将同一个档案所属的 blocks 汇整在一起, 这样资料的读取会比较容易啊! 想当然尔, FAT 的档案系统需要三不五时的碎片整理一下, 那么 Ext2 是否需要磁盘重整呢?
由于 Ext2 是索引式档案系统, 基本上不太需要常常进行碎片整理的. 但是如果档案系统使用太久, 常常删除 / 编辑 / 新增档案时, 那么还是可能会造成档案资料太过于离散的问题, 此时或许会需要进行重整一下的.
Linux 的 EXT2 档案系统(inode)
inode 的内容在记录档案的权限与相关属性, 至于 block 区块则是在记录档案的实际内容. 而且档案系统一开始就将 inode 与 block 规划好了, 除非重新格式化(或者利用 resize2fs 等指令变更档案系统大小), 否则 inode 与 block 固定后就不再变动. 但是如果仔细考虑一下, 如果我的档案系统高达数百 GB 时, 那么将所有的 inode 与 block 通通放置在一起将是很不智的决定, 因为 inode 与 block 的数量太庞大, 不容易管理.
为此, 因此 Ext2 档案系统在格式化的时候基本上是区分为多个区块群组(block group) 的, 每个区块群组都有独立的 inode/block/superblock 系统. 感觉上就好像我们在当兵时, 一个营里面有分成数个连, 每个连有自己的联络系统, 但最终都向营部回报连上最正确的信息一般! 这样分成一群群的比较好管理啦! 整个来说, Ext2 格式化后有点像底下这样:
在整体的规划当中, 档案系统最前面有一个开机磁区 (boot sector), 这个开机磁区可以安装开机管理程式, 这是个非常重要的设计, 因为如此一来我们就能够将不同的开机管理程式安装到个别的档案系统最前端, 而不用覆盖整颗磁盘唯一的 MBR, 这样也才能够制作出多重开机的环境啊! 至于每一个区块群组(block group) 的六个主要内容说明如后:
data block (资料区块)
data block 是用来放置档案内容资料地方, 在 Ext2 档案系统中所支持的 block 大小有 1K, 2K 及 4K 三种而已. 在格式化时 block 的大小就固定了, 且每个 block 都有编号, 以方便 inode 的记录啦. 不过要注意的是, 由于 block 大小的差异, 会导致该档案系统能够支持的最大磁盘容量与最大单一档案容量并不相同. 因为 block 大小而产生的 Ext2 档案系统限制如下:
Block 大小 | 1KB | 2KB | 4KB |
---|---|---|---|
最大单一档案限制 | 16GB | 256GB | 2TB |
最大档案系统总容量 | 2TB | 8TB | 16TB |
除此之外 Ext2 档案系统的 block 还有什么限制呢? 有的! 基本限制如下:
原则上, block 的大小与数量在格式化完就不能够再改变了(除非重新格式化);
每个 block 内最多只能够放置一个档案的资料;
承上, 如果档案大于 block 的大小, 则一个档案会占用多个 block 数量;
承上, 若档案小于 block , 则该 block 的剩余容量就不能够再被使用了(磁盘空间会浪费).
inode table (inode 表格)
基本上, 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 哪有这么多可记录的信息? 为此我们的系统很聪明的将 inode 记录 block 号码的区域定义为 12 个直接, 一个间接, 一个双间接与一个三间接记录区. 这是啥? 我们将 inode 的结构画一下好了.
这样子 inode 能够指定多少个 block 呢? 我们以较小的 1K block 来说明好了, 可以指定的情况如下:
12 个直接指向: 12*1K=12K
由于是直接指向, 所以总共可记录 12 笔记录, 因此总额大小为如上所示;
间接: 256*1K=256K
每笔 block 号码的记录会花去 4bytes, 因此 1K 的大小能够记录 256 笔记录, 因此一个间接可以记录的档案大小如上;
双间接: 256*256*1K=256 2 K
第一层 block 会指定 256 个第二层, 每个第二层可以指定 256 个号码, 因此总额大小如上;
三间接: 256*256*256*1K=256 3 K
第一层 block 会指定 256 个第二层, 每个第二层可以指定 256 个第三层, 每个第三层可以指定 256 个号码, 因此总额大小如上;
总额: 将直接, 间接, 双间接, 三间接加总, 得到 12 + 256 + 256*256 + 256*256*256 (K) = 16GB
Superblock (超级区块)
记录的信息主要有:
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. 相关的 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 来记录呢? 当然是选择『空的 block 』来记录新档案的资料啰. 那你怎么知道哪个 block 是空的? 这就得要透过 block bitmap 的辅助了. 从 block bitmap 当中可以知道哪些 block 是空的, 因此我们的系统就能够很快速的找到可使用的空间来处置档案啰.
同样的, 如果你删除某些档案时, 那么那些档案原本占用的 block 号码就得要释放出来, 此时在 block bitmap 当中相对应到该 block 号码的标志就得要修改成为『未使用中』啰! 这就是 bitmap 的功能.
inode bitmap (inode 对照表)
这个其实与 block bitmap 是类似的功能, 只是 block bitmap 记录的是使用与未使用的 block 号码, 至于 inode bitmap 则是记录使用与未使用的 inode 号码啰!
dumpe2fs: 查询 Ext 家族 superblock 信息的指令
[root@study ~]# dumpe2fs [-bh]装置档名
选项与参数:
-b : 列出保留为坏轨的部分(一般用不到吧!?)
-h : 仅列出 superblock 的资料, 不会列出其他的区段内容!
范例: 鸟哥的一块 1GB ext4 档案系统内容
- [root@study ~]# blkid <== 这个指令可以叫出目前系统有被格式化的装置
- /dev/vda1: LABEL="myboot" UUID="ce4dbf1b-2b3d-4973-8234-73768e8fd659" TYPE="xfs"
- /dev/vda2: LABEL="myroot" UUID="21ad8b9a-aaad-443c-b732-4e2522e95e23" TYPE="xfs"
- /dev/vda3: UUID="12y99K-bv2A-y7RY-jhEW-rIWf-PcH5-SaiApN" TYPE="LVM2_member"
/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: <none> #档案系统的名称(不一定会有)
- Last mounted on: <not available> #上一次挂载的目录位置
- 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: 3c2568b4-1a7e-44cf-95a2-c8867fb19fbc
- Journal backup: inode blocks
- Journal features: (none)
- Journal size: 32M # Journal 日志式资料的可供纪录总容量
- Journal length: 8192
- Journal sequence: 0x00000001
- 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 (+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, 4258-32767 #底下两行说明剩余的容量有多少
- Free inodes: 12-8192
- Group 1: (Blocks 32768-65535) [INODE_UNINIT] #后续为更多其他的 block group 喔!
- ....(底下省略)....
- # 由于资料量非常的庞大, 因此鸟哥将一些信息省略输出了! 上表与你的萤幕会有点差异.
- # 前半部在秀出 supberblock 的内容, 包括标头名称 (Label) 以及 inode/block 的相关信息
- # 后面则是每个 block group 的个别信息了! 您可以看到各区段资料所在的号码!
- # 也就是说, 基本上所有的资料还是与 block 的号码有关就是了! 很重要!
至于 block group 的内容我们单纯看 Group0 信息好了. 从上表中我们可以发现:
Group0 所占用的 block 号码由 0 到 32767 号, superblock 则在第 0 号的 block 区块内!
档案系统描述说明在第 1 号 block 中;
block bitmap 与 inode bitmap 则在 129 及 145 的 block 号码上.
至于 inode table 分布于 161-672 的 block 号码中!
由于 (1) 一个 inode 占用 256 bytes ,(2)总共有 672 - 161 + 1(161 本身) = 512 个 block 花在 inode table 上, (3)每个 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 这个选项来处理:
- [root@study ~]# ls -li
- total 8
- 53735697 -rw-------. 1 root root 1816 May 4 17:57 anaconda-ks.cfg
- 53745858 -rw-r--r--. 1 root root 1864 May 4 18:01 initial-setup-ks .cfg
而由这个目录的 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 block
dr-xr- xr-x. 4 root root 4096 May 4 17:59 /boot <== 1 个 4K block
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
档案:
当我们在 Linux 下的 ext2 建立一个一般档案时, ext2 会分配一个 inode 与相对于该档案大小的 block 数量给该档案. 例如: 假设我的一个 block 为 4 Kbytes , 而我要建立一个 100 KBytes 的档案, 那么 Linux 将分配一个 inode 与 25 个 block 来储存该档案! 但同时请注意, 由于 inode 仅有 12 个直接指向, 因此还要多一个 block 来作为区块号码的记录喔!
目录树读取:
我们提到『新增 / 删除 / 更名档名与目录的 w 权限有关』! 那是因为档名是记录在目录的 block 当中, 因此当我们要读取某个档案时, 就务必会经过目录的 inode 与 block , 然后才能够找到那个待读取档案的 inode 号码, 最终才会读到正确的档案的 block 内的资料.
由于目录树是由根目录开始读起, 因此系统透过挂载的信息可以找到挂载点的 inode 号码, 此时就能够得到根目录的 inode 内容, 并依据该 inode 读取根目录的 block 内的档名资料, 再一层一层的往下读到正确的档名. 举例来说, 如果我想要读取 / etc/passwd 这个档案时, 系统是如何读取的呢?
- [root@study ~]# ll -di //etc /etc/passwd
- 128 dr-xr-x r-x . 17 root root 4096 May 4 17:56 /
- 33595521 drwxr-x r-x . 131 root root 8192 Jun 17 00:20 /etc
- 36628004 -rw-r-- r-- . 1 root root 2092 Jun 17 00:20 /etc/passw
该档案的读取流程为(假设读取者身份为 dmtsai 这个一般身份使用者):
/ 的 inode:
透过挂载点的信息找到 inode 号码为 128 的根目录 inode, 且 inode 的权限属性允许我们可以读取该 block 的内容(有 r 与 x) ;
/ 的 block:
经过上个步骤取得 block 的号码, 并找到该内容有 etc / 目录的 inode 号码(33595521);
etc / 的 inode:
读取 33595521 号 inode 得知 dmtsai 具有 r 与 x 的权限, 因此可以读取 etc / 的 block 内容;
etc / 的 block:
经过上个步骤取得 block 号码, 并找到该内容有 passwd 档案的 inode 号码(36628004);
passwd 的 inode:
读取 36628004 号 inode 得知 dmtsai 具有 r 的权限, 因此可以读取 passwd 的 block 内容;
passwd 的 block:
最后将该 block 内容的资料读出来.
来源: http://www.bubuko.com/infodetail-2946474.html