块组
文件系统格式化时首先会分为多个块,而多个块又能组成一个块组(block groups)。
每一个块组中也保存了自身的描述信息,如:
- 这个块组的组成是由哪个块到哪个块;
- 每个块组中有多少个块、有多少已使用的块、有多少空闲的块;
- 每个块组中有多少个 inode、多少已用的 inode、多少空闲的 inode;
每一个块组的详细信息都是保存在组自己的描述块当中,使用dumpe2fs /dev/DEVICE
就能查看到块组的详细信息。
超级块
超级块用来描述整个文件系统的大图景结构的组成形式,如:
- 文件系统中有多少个块组;
- 挂载选项信息等等,
这些信息就保存在超级块当中,通过 tune2fs -l DEVICE
看到的信息就是超级块中的信息。
超级块可能放在某块组中的某一个位置(格式化时有提示),描述的都是相对高层次的、抽象的信息。
Inode
Inode 也叫 Index Node,称作索引节点。
整个数据是由数据和元数据组成,每一个文件都有它的元数据(属性信息),包括它的大小、时间戳、权限、属主、属组等信息。
每一个能够存储单个文件的所有属性信息、并且是按照特定格式组织的存储空间就称之为一个索引节点。
为了对多个 Inode 进行区分,每个索引节点也有它的编号,称之为 Inode 号(Inode Number)。
访问任何文件时,都先要找到这个文件的 Inode,并通过 Inode 知道该文件的数据存储在哪些 block 块上,然后找到对应的 block 块。
在 Inode 上描述数据存储在哪些块上的信息也叫做地址指针,由于单个地址指针所描述的块信息有限,地址指针又分为直接指针、间接指针、三级指针。顾名思义,间接与三级指针能够指向另外一片乃至多片描述块信息的地址区(类似于扩展分区),让一个 Inode 能够描述更多的块信息。
文件块只有被 Inode 引用了才能真正的使用。
以新建一个文件为例:
- 首先要在元数据区找一个空闲区创建一个 Inode。事实上为了让 Inode 更加快速的创建存储,在文件系统格式化完成时在元数据区已经分配了专门 Inode 区间,且这个 Inode 区间的大小是固定的,该区间存放了 Inode,每一个 Inode 又有它的标志位,1 就表示非空闲,0 则表示该 Inode 是空闲。所以创建 Inode 实际上就是在 Inode 区间找到一个空闲的 Inode 存放文件信息;
- 接着在数据区在找到空闲的块(每一个块也有它的标志位,0 则表示该块空闲,1 则表示该块已被使用)存放数据信息;
由于 Inode 数量也太过庞大 ,如果想要直接找一个空闲的 Inode 也很困难,所以文件系统一般也会对 Inode 进行再次索引(Inode 实际上是对文件系统中块信息的索引),这个索引叫做位图索引(Inode bitmap),它会对位标识每个 Inode 空闲与否的状态信息。
对于整个文件系统来说,即便是位图索引,数量也依旧是庞大的,所以在文件系统中每个块组中也有它对自己组中的块的索引,叫做 Inode 表(Inode table)。
文件名也是元信息,但是它并不是存放在 Inode 中。
硬链接
硬链接指的是两个不同的路径指向相同的 Inode,即最终的结果就是两个不同的文件名指向了存放了相同数据的相同文件;
通过 ls -l
查看目录:
第二列的这个数字其实指的就是该文件被硬链接的次数,即文件对应 Inode 被引用的次数,也描述了该文件被多少个路径引用了,它存放在 Inode 中。每次删除一个引用(硬链接),该数字就会减 1,如果为 0,那么对应 Inode标志位就会置为 0,即修改对应 Inode 为空闲状态。
正常删除一个文件只是修改对应文件的 Inode 以及数据块为空闲状态,并没有真正的删除对应的数据,这也是数据删除后能被恢复的原因。之后如果新建或修改数据要使用新的 Inode 和数据块,则直接找到空闲状态的 Inode 和数据块,覆盖其对应的Inode 和数据块信息即可。
硬链接可以通过ln
命令来创建,看如下示例:
[root@localhost ~]# ln test1.sh test1.sh.hl
[root@localhost ~]# ls -li
33574990 -rw-------. 1 root root 1215 3月 27 2019 anaconda-ks.cfg
36283213 -rwxr-xr-x. 2 root root 30 9月 17 21:26 test1.sh
36283213 -rwxr-xr-x. 2 root root 30 9月 17 21:26 test1.sh.hl
可以看到,通过 ln test1.sh test1.sh.hl
创建了一个硬链接 test1.sh.hl
和 test1.sh
使用同一个 Inode,它们被硬链接的次数也变成了 2,并且使用 ls -i
也可以看到它们的 Inode 号是相同的。
ls
命令的-i
选项可以查看到对应文件的 Inode 号码。
注意:
- 硬链接是不能对目录创建的,因为如果在目录下有一个硬链接指向了目录本身,那么会出现循环引用;
- 硬链接不能够跨分区创建,因为每个分区的 Inode 索引是独立的;
软链接
软链接也叫符号链接,一个正常的文件或路径一般来说会通过地址指针最终指向一个数据块,而对于软链接文件来说,它最终通过数据指针指向的不是数据块,而是一个字符串,该字符串描述了另一个文件路径,即软链接实际上就是对文件路径的引用。
看如下示例:
可以看到 system-release
文件是一个软链接,它指向了同目录下的 centos-release
位置,并且可以看到 system-release
文件和 centos-release
文件的文件大小是不同的,原因是 centos-release
大小是它的 Inode 指向的真实数据大小,而 system-release
的大小就是它指向的路径字符串的大小(上述大小单位为字节)。
软链接同样可以通过 ln
命令创建,只不过此时要使用它的 -s
选项,看如下示例:
[root@localhost ~]# ln -s test1.sh test1.sh.sl
[root@localhost ~]# ls -li
33574990 -rw-------. 1 root root 1215 3月 27 2019 anaconda-ks.cfg
36283213 -rwxr-xr-x. 2 root root 30 9月 17 21:26 test1.sh
36282569 lrwxrwxrwx. 1 root root 8 9月 28 14:04 test1.sh.sl -> test1.sh
可以看到,通过 ln -s test1.sh test1.sh.sl
创建了一个软链接 test1.sh.hl
指向 test1.sh
路径字符串,大小为该字符串的字节大小,Inode 号也与 test1.sh
文件不同。
注意:
- 软链接是可以对目录创建的,因为软链接对目录来说实际上就是目录的路径字符串,不会造成同硬链接的循环引用;
- 软链接是可以跨分区的,因为路径字符串是可以描述其它分区的文件的;
练习
1、创建一个 20G
的文件系统,块大小为 2048
,文件系统为 ext4
,卷标为 TEST
,要求此分区开机后自动挂载到 /testing
目录,且默认有 acl
挂载选项。
步骤如下:
- 使用
fdisk
创建 20g 大小的分区; mke2fs -t ext4 -b 2048 -L 'TEST' /dev/DEVICE
;- 编辑
/etc/fstab
配置自动挂载,LABEL='TEST' /testing ext4 defaults,acl 0 0
;
2、写一个脚本,完成如下功能:
- 列出当前系统识别到的所有磁盘设备;
- 如果磁盘数量为 1,则显示其空间使用信息,否则,显示最后一个磁盘上的空间使用信息;
#!/bin/bash
#
disk_count=$(fdisk -l | egrep '^磁盘 /dev/[sh]d[a-z]' | wc -l)
if [ $disk_count -eq 1 ]; then
fdisk -l /dev/[sh]da;
else
fdisk -l $(fdisk -l /dev/[sh]d[a-z] | grep -o '磁盘 /dev/[sh]d[a-z]' | tail -1 | cut -d' ' -f2);
fi
评论区