个人随笔 (Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu)
参考资料
参考:https://www.nongnu.org/ext2-doc/ext2.pdf
参考:https://developer.aliyun.com/article/297657
参考:https://www.bilibili.com/read/cv17345430/
参考:https://github.com/torvalds/linux/blob/master/fs/ext2/ext2.h
参考:https://baike.baidu.com/item/e2fsprogs/6202376?fr=ge_ala
参考:https://www.easeus.com/partition-master/ext2-ext3-ext4-file-system-format-and-difference.html
1. 引言
对于ext2文件系统,我们大多数会有所耳闻的,那我们是否知道,该文件系统的内部存储结构是什么样的?
另外对于一个制定大小的文件系统,它的存储大小和文件数有约束吗?
一个10MB的ext2文件系统中:
能支持建立多少个文件?能建立1000个?10000个?和什么有关系?
能最大存储多大的内容,是满10MB吗?还是9MB?由什么来确定的?
这些问题,我们可以借助dump2fs命令的使用,来做一个初步的探究。
2. dumpe2fs查看信息
创建出loop device之后,使用命令如下,来查看ext2设备的信息。
创建loop device的方法,参考文章下面附录中方法。
shell
[root@ls_CxhK1nVN ~]# dumpe2fs /dev/loop0
[root@ls_CxhK1nVN ~]# dumpe2fs /dev/loop1
下面是一个新创建的10MB的loop deivce的信息:
10MB的内容如下:
shell
[root@ls_CxhK1nVN ~]# dumpe2fs /dev/loop1
dumpe2fs 1.45.6 (20-Mar-2020)
Filesystem volume name: <none>
Last mounted on: /root/mongodir
Filesystem UUID: 10f36aab-aa44-4d96-8733-ee31bd6bed5f
Filesystem magic number: 0xEF53
Filesystem revision #: 1 (dynamic)
Filesystem features: ext_attr resize_inode dir_index filetype sparse_super large_file
Filesystem flags: signed_directory_hash
Default mount options: user_xattr acl
Filesystem state: not clean
Errors behavior: Continue
Filesystem OS type: Linux
Inode count: 2560
Block count: 10240
Reserved block count: 512
Free blocks: 9819
Free inodes: 2549
First block: 1
Block size: 1024
Fragment size: 1024
Reserved GDT blocks: 39
Blocks per group: 8192
Fragments per group: 8192
Inodes per group: 1280
Inode blocks per group: 160
Filesystem created: Thu Mar 14 15:11:03 2024
Last mount time: Thu Mar 14 15:11:48 2024
Last write time: Thu Mar 14 15:11:48 2024
Mount count: 1
Maximum mount count: -1
Last checked: Thu Mar 14 15:11:03 2024
Check interval: 0 (<none>)
Reserved blocks uid: 0 (user root)
Reserved blocks gid: 0 (group root)
First inode: 11
Inode size: 128
Default directory hash: half_md4
Directory Hash Seed: 3bd0f015-62fe-4eb2-b815-0fed1e1ebf11
Group 0: (Blocks 1-8192)
Primary superblock at 1, Group descriptors at 2-2
Reserved GDT blocks at 3-41
Block bitmap at 42 (+41)
Inode bitmap at 43 (+42)
Inode table at 44-203 (+43)
7975 free blocks, 1269 free inodes, 2 directories
Free blocks: 218-8192
Free inodes: 12-1280
Group 1: (Blocks 8193-10239)
Backup superblock at 8193, Group descriptors at 8194-8194
Reserved GDT blocks at 8195-8233
Block bitmap at 8234 (+41)
Inode bitmap at 8235 (+42)
Inode table at 8236-8395 (+43)
1844 free blocks, 1280 free inodes, 0 directories
Free blocks: 8396-10239
Free inodes: 1281-2560
3. 信息解析
通过上述信息,我们关注到:
-
Block总量,Block count * Block size = 10MB,正好是一个block1KB,10240个block。
Block count: 10240
Block size: 1024
-
Inode节点数量,Inode count * Inode size = 320 * 1024;
将会占用320个block,正好有2个Group,1个Group存储160个,和下面的信息相互印证了。
Inode count: 2560
Inode size: 128
Inode blocks per group: 160
Group 0: (Blocks 1-8192)
Inode table at 44-203 (+43)
Group 1: (Blocks 8193-10239)
Inode table at 8236-8395 (+43)
-
关注初始创建后的空闲block数量,空闲inode数量
空闲block数量将决定存储容量的门限:9819 * 1024 = 9819KB,比10240少421个Blocks。
空闲inodes数量将决定可创建文件数量的门限:2549个文件
Free blocks: 9819
Free inodes: 2549
-
关注Block count / Inode count比值 = 4,不考虑文件系统占用情况下,每4KB会支持建立一个文件;
推算得出:基于10MB是2560个文件,那么1GB就是256,000, 1TB就是256,000,000个文件,支持的文件数量还是非常多的。
Block count: 10240
Block size: 1024
Inode count: 2560
-
Group Table的大小与Bitmap关系,Blocks per group * 1024 = 8MB。
每个Group大小是8MB;当前总大小10MB,拆分处了一个8MB,一个约2MB的group。
为什么Group大小采用8MB,这个和Bitmap有关系吗?是有关系的,Bitmap占据一个block,也就是1024字节,也是1024*8=8192比特。
Bitmap最多能指示8192个block的使用情况,而Group Table也正式采用的8192个block组成,刚好Bitmap可以全部指示出来。
Blocks per group: 8192
Block size: 1024
Group 0: (Blocks 1-8192)
Group 1: (Blocks 8193-10239)
4. 总体结构解析
基于上面的分析,侧面也可以佐证,ext2文件系统的layout结构信息
对于上面10MB的信息结构解析如下:
- filesystem boot header
开头的1024字节,也即block 0,作为boot预留字节,通常是全0值。
Block Offset | Length | Description |
---|---|---|
byte 0 | byte 512 | boot record (if present) |
512 bytes | byte 512 | additional boot record data (if present) |
- block group 0, blocks 1 to 8192
第0个table group,空间充足情况下,每个table group都有8192个block组成。
地0个table group的第一个block放的是superblock,之后是block group desciptor table。
Block Offset | Length | Description |
---|---|---|
byte 1024 | 1024 bytes | superblock |
block 2 | 1 block | block group descriptor table |
block 3 | 39 block | Reserved GDT blocks |
block 42 | 1 block | block bitmap |
block 43 | 1 block | inode bitmap |
block 44 | 160 blocks | inode table |
block 204 | 7989 blocks | data blocks |
- block group 1, blocks 8193 to 10239
第1个table group,空间不充情况下,剩余的block组成最后一个table group。
第1, 3, 5, 7,以及3, 5, 7的幂中会放入backup super block以及后续的block group desciptor;
非这些的剩余group中,直接放的是block bitmap及剩余的信息,这点可以参见30MB时的第2个group的信息。
Block Offset | Length | Description |
---|---|---|
block 8193 | 1024 bytes | Backup superblock |
block 8194 | 1 block | block group descriptor table |
block 8195 | 39 block | Reserved GDT blocks |
block 8234 | 1 block | block bitmap |
block 8235 | 1 block | inode bitmap |
block 8236 | 160 blocks | inode table |
block 8396 | 1844 blocks | data blocks |
5. 附录:对照一个30MB的文件dumpe2fs信息
下面是使用dump2fs命令,来查看一个30MB的loop device内容,可以作为和上面信息的对比参考。
30MB的内容如下:
shell
[root@ls_CxhK1nVN ~]# dumpe2fs /dev/loop2
dumpe2fs 1.45.6 (20-Mar-2020)
Filesystem volume name: <none>
Last mounted on: /root/appledir
Filesystem UUID: 66ccabd0-1809-4cae-a1d4-503fd0c5bb42
Filesystem magic number: 0xEF53
Filesystem revision #: 1 (dynamic)
Filesystem features: ext_attr resize_inode dir_index filetype sparse_super large_file
Filesystem flags: signed_directory_hash
Default mount options: user_xattr acl
Filesystem state: not clean
Errors behavior: Continue
Filesystem OS type: Linux
Inode count: 7680
Block count: 30720
Reserved block count: 1536
Free blocks: 29374
Free inodes: 7669
First block: 1
Block size: 1024
Fragment size: 1024
Reserved GDT blocks: 119
Blocks per group: 8192
Fragments per group: 8192
Inodes per group: 1920
Inode blocks per group: 240
Filesystem created: Fri Mar 15 11:40:10 2024
Last mount time: Fri Mar 15 11:40:15 2024
Last write time: Fri Mar 15 11:40:15 2024
Mount count: 1
Maximum mount count: -1
Last checked: Fri Mar 15 11:40:10 2024
Check interval: 0 (<none>)
Reserved blocks uid: 0 (user root)
Reserved blocks gid: 0 (group root)
First inode: 11
Inode size: 128
Default directory hash: half_md4
Directory Hash Seed: e5834267-fbd0-4b52-a1ea-a1ae4418bb95
Group 0: (Blocks 1-8192)
Primary superblock at 1, Group descriptors at 2-2
Reserved GDT blocks at 3-121
Block bitmap at 122 (+121)
Inode bitmap at 123 (+122)
Inode table at 124-363 (+123)
7815 free blocks, 1909 free inodes, 2 directories
Free blocks: 378-8192
Free inodes: 12-1920
Group 1: (Blocks 8193-16384)
Backup superblock at 8193, Group descriptors at 8194-8194
Reserved GDT blocks at 8195-8313
Block bitmap at 8314 (+121)
Inode bitmap at 8315 (+122)
Inode table at 8316-8555 (+123)
7829 free blocks, 1920 free inodes, 0 directories
Free blocks: 8556-16384
Free inodes: 1921-3840
Group 2: (Blocks 16385-24576)
Block bitmap at 16385 (+0)
Inode bitmap at 16386 (+1)
Inode table at 16387-16626 (+2)
7950 free blocks, 1920 free inodes, 0 directories
Free blocks: 16627-24576
Free inodes: 3841-5760
Group 3: (Blocks 24577-30719)
Backup superblock at 24577, Group descriptors at 24578-24578
Reserved GDT blocks at 24579-24697
Block bitmap at 24698 (+121)
Inode bitmap at 24699 (+122)
Inode table at 24700-24939 (+123)
5780 free blocks, 1920 free inodes, 0 directories
Free blocks: 24940-30719
Free inodes: 5761-7680
5. 附录:如何创建一个10MB的loop device
如何创建一个10MB的loop device,方法如下:
shell
[root@ls_CxhK1nVN ~]# dd if=/dev/zero of=./mongo bs=1K count=10240
10240+0 records in
10240+0 records out
10485760 bytes (10 MB, 10 MiB) copied, 0.0155913 s, 673 MB/s
[root@ls_CxhK1nVN ~]# losetup /dev/loop1 ./mongo
[root@ls_CxhK1nVN ~]# losetup -a
/dev/loop1: [64769]:395659 (/root/mongo)
/dev/loop0: [64769]:395656 (/bean)
[root@ls_CxhK1nVN ~]# mke2fs /dev/loop1
mke2fs 1.45.4 (23-Sep-2019)
Discarding device blocks: done
Creating filesystem with 10240 1k blocks and 2560 inodes
Filesystem UUID: 10f36aab-aa44-4d96-8733-ee31bd6bed5f
Superblock backups stored on blocks:
8193
Allocating group tables: done
Writing inode tables: done
Writing superblocks and filesystem accounting information: done
[root@ls_CxhK1nVN ~]# mkdir mongodir
[root@ls_CxhK1nVN ~]# mount -t ext2 /dev/loop1 mongodir
[root@ls_CxhK1nVN ~]# dumpe2fs /dev/loop1
6. 附录:如何写一个脚本来验证创建文件的个数限制:
创建文件的shell脚本如下,执行该脚本,创建文件测试文件的支持数量;
当创建文件失败时,会报错:
touch: cannot touch 'files/file_2548.txt': No space left on device
使用chatgpt输出的脚本;
shell
[root@ls_CxhK1nVN mongodir]# cat createfile.sh
#!/bin/bash
# 指定文件夹路径
folder="files"
# 创建文件夹
mkdir -p "$folder"
# 循环创建1000个文件
for ((i=1; i<=2549; i++))
do
# 生成文件名
filename="$folder/file_$i.txt"
# 创建文件
touch "$filename"
# 输出创建的文件名
echo "Created file: $filename"
done
个人随笔 (Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu)