ext2文件系统学习札记

// 以下为ext2文件系统相关的学习笔记/******************************************************/
利用/dev/loop*制作块设备以及挂载文件系统
dd if=/dev/zero of=test_block bs=1K count=512000 // 新建块500M的空间
losetup /dev/loop6 ./test_block // 将这一块空间和/dev/loop6挂钩,使/dev/loop6为块设备
cat /proc/partitions // 查看具体的分区
7 6 512000 loop6


// 把设备制作成一个ext盘
[root@A23320569 fs_test]# mke2fs /dev/loop6
mke2fs 1.42.9 (28-Dec-2013)
Discarding device blocks: done
Filesystem label=
OS type: Linux
Block size=1024 (log=0) // 块大小 1024BYTE
Fragment size=1024 (log=0)
Stride=0 blocks, Stripe width=0 blocks
128016 inodes, 512000 blocks // inode blocks总个数
25600 blocks (5.00%) reserved for the super user
First data block=1
Maximum filesystem blocks=67633152
63 block groups // 63个块组
8192 blocks per group, 8192 fragments per group // 一个group有8192个块
2032 inodes per group // 一个块组有2032个inode
Superblock backups stored on blocks:  // superblock备份,可用于文件系统恢复
8193, 24577, 40961, 57345, 73729, 204801, 221185, 401409
Allocating group tables: done
Writing inode tables: done
Writing superblocks and filesystem accounting information: done

// 把盘挂载到具体的目录下面
mount -t ext2 /dev/loop6 ./mount_ext2/ 

// 查看具体文件系统的信息
[root@A23320569 mount_ext2]# dumpe2fs /dev/loop6
dumpe2fs 1.42.9 (28-Dec-2013)
Filesystem volume name: <none>
Last mounted on: <not available>
Filesystem UUID: d902a97b-a43f-4f24-bf17-4a076c5ca111
Filesystem magic number: 0xEF53
Filesystem revision #: 1 (dynamic)
Filesystem features: ext_attr resize_inode dir_index filetype sparse_super
Filesystem flags: signed_directory_hash
Default mount options: user_xattr acl
Filesystem state: not clean
Errors behavior: Continue
Filesystem OS type: Linux
Inode count: 128016
Block count: 512000
Reserved block count: 25600
Free blocks: 493526
Free inodes: 128005
First block: 1
Block size: 1024
Fragment size: 1024
Reserved GDT blocks: 256
Blocks per group: 8192
Fragments per group: 8192
Inodes per group: 2032
Inode blocks per group: 254
Filesystem created: Sat Jan 6 15:56:03 2018
Last mount time: Sat Jan 6 16:01:34 2018
Last write time: Sat Jan 6 16:01:34 2018
Mount count: 1
Maximum mount count: -1
Last checked: Sat Jan 6 15:56:03 2018
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: bdc5a122-5fa8-4ee4-8f0b-29b3906d1b32

Group 0: (Blocks 1-8192) // 从block1开始,因为第一个块block0上存储了启动扇区(主引导分区( 引导程序)以及分区表),所以第一个块组从block1开始(不是很妥当)
Primary superblock at 1, Group descriptors at 2-3 // 第一个块存储了超级块,block2-3存储了文件系统描述符(组描述符)
Reserved GDT blocks at 4-259
Block bitmap at 260 (+259), Inode bitmap at 261 (+260) block位图用一个块来表示,即1K=1024byte=1024*8=8192bits,所以一个块组有8192个块
Inode table at 262-515 (+261)
7663 free blocks, 2021 free inodes, 2 directories
Free blocks: 530-8192
Free inodes: 12-2032
Group 1: (Blocks 8193-16384)
Backup superblock at 8193, Group descriptors at 8194-8195
Reserved GDT blocks at 8196-8451
Block bitmap at 8452 (+259), Inode bitmap at 8453 (+260)
Inode table at 8454-8707 (+261)
7677 free blocks, 2032 free inodes, 0 directories
Free blocks: 8708-16384
Free inodes: 2033-4064
Group 2: (Blocks 16385-24576)
Block bitmap at 16385 (+0), Inode bitmap at 16386 (+1)
Inode table at 16387-16640 (+2)
7936 free blocks, 2032 free inodes, 0 directories
Free blocks: 16641-24576
Free inodes: 4065-6096
Group 3: (Blocks 24577-32768)
Backup superblock at 24577, Group descriptors at 24578-24579
Reserved GDT blocks at 24580-24835
Block bitmap at 24836 (+259), Inode bitmap at 24837 (+260)
Inode table at 24838-25091 (+261)
7677 free blocks, 2032 free inodes, 0 directories
Free blocks: 25092-32768
Free inodes: 6097-8128
。。。。。。。。。。。。。。。。。。。。。
Group 62: (Blocks 507905-511999)
Block bitmap at 507905 (+0), Inode bitmap at 507906 (+1)
Inode table at 507907-508160 (+2)
3839 free blocks, 2032 free inodes, 0 directories
Free blocks: 508161-511999
Free inodes: 125985-128016

//把最前面200k dump出来查看 超级块 dd if=/dev/loop6 bs=1k count=200 | od -tx1 -Ax > ./dump_hex
000400 10 f4 01 00 00 d0 07 00 00 64 00 00 d6 87 07 00
000410 05 f4 01 00 01 00 00 00 00 00 00 00 00 00 00 00
000420 00 20 00 00 00 20 00 00 f0 07 00 00 5e 82 50 5a
000430 5e 82 50 5a 01 00 ff ff 53 ef 00 00 01 00 00 00
000440 13 81 50 5a 00 00 00 00 00 00 00 00 01 00 00 00
000450 00 00 00 00 0b 00 00 00 80 00 00 00 38 00 00 00
000460 02 00 00 00 01 00 00 00 d9 02 a9 7b a4 3f 4f 24
000470 bf 17 4a 07 6c 5c a1 11 00 00 00 00 00 00 00 00
000480 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
struct ext2_super_block{
  __u32 s_inodes_count; /* Inodes count */ inode总数 0x01f410 = 128016,和之前导出的数据一致
  __u32 s_blocks_count; /* Blocks count */ 0x07d000 = 512000,和之前的一致
  __u32 s_r_blocks_count; /* Reserved blocks count */ 0x6400 = 25600
  __u32 s_free_blocks_count; /* Free blocks count */ 0x0787d6 = 493526
  __u32 s_free_inodes_count; /* Free inodes count */ 0x01f405 = 128005
  __u32 s_first_data_block; /* First Data Block */ 1
  __u32 s_log_block_size; /* Block size */
  __s32 s_log_frag_size; /* Fragment size */
  ...........
}

查看组描述符 2-3个block里面是组描述符 ->0x800 = 2048 一共63个块组
000800 04 01 00 00 05 01 00 00 06 01 00 00 ef 1d e5 07
000810 02 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 // 块组0
000820 04 21 00 00 05 21 00 00 06 21 00 00 fd 1d f0 07
000830 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 // 块组1
000840 01 40 00 00 02 40 00 00 03 40 00 00 00 1f f0 07
000850 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 // 块组2
000860 04 61 00 00 05 61 00 00 06 61 00 00 fd 1d f0 07
000870 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00

000fa0 01 a0 07 00 02 a0 07 00 03 a0 07 00 00 1f f0 07
000fb0 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 // 块组61
000fc0 01 c0 07 00 02 c0 07 00 03 c0 07 00 ff 0e f0 07
000fd0 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 // 块组62
000fe0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
001000 04 20 00 00 04 60 00 00 04 a0 00 00 04 e0 00 00
其余组的 块组描述符是这个的备份,通过

dd if=/dev/loop6 bs=1k skip=24578 count=2 | od -tx1 -Ax > ./tmp1.txt 可以对比两个数据是一样的

// 查看目录项以及具体的内容
方法一:通过debugfs
raw 为挂载ext2文件系统目录下的一个目录
[root@A23320569 raw]# ll -ai
total 5
103633 drwxr-xr-x 3 root root 1024 Jan 8 16:05 .
2          drwxr-xr-x 5 root root 1024 Jan 8 16:00 .. // inode号从1开始?
103634 -rw-r--r-- 1 root root 13 Jan 8 16:05 hello
103635 drwxr-xr-x 2 root root 1024 Jan 8 16:05 sub_dir
103638 -rw-r--r-- 1 root root 16 Jan 8 16:05 test

debugfs /dev/loop6
debugfs 1.42.9 (28-Dec-2013)
debugfs: stat <103633> // 统计103633 的信息,即一个目录的信息
Inode: 103633 Type: directory Mode: 0755 Flags: 0x0
Generation: 3290864468 Version: 0x00000010
User: 0 Group: 0 Size: 1024
File ACL: 0 Directory ACL: 0
Links: 3 Blockcount: 2
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x5a532650 -- Mon Jan 8 16:05:36 2018
atime: 0x5a532652 -- Mon Jan 8 16:05:38 2018
mtime: 0x5a532650 -- Mon Jan 8 16:05:36 2018
BLOCKS:
(0):418049 // inode对应的文件内容所在的块号
TOTAL: 1 // inode对应的文件占用的块数,一共一个(也就几个目录,一个块足够了)

dd if=/dev/loop6 bs=1k skip=418049 count=1 | od -tx1 -Ax > dir_rar.txt // dump出418049个块的数据
000000 d1 94 01 00 0c 00 01 02 2e 00 00 00 02 00 00 00 // inode:0x194d1=103633 rec_len:0c name_len:01 file_type:02 name:.(2e) // 第一个条目
000010 0c 00 02 02 2e 2e 00 00 d2 94 01 00 10 00 05 01 // inode:0x02 rec_len:0c name_len:02 file_type:02 name:2e 2e // 第二个条目
000020 68 65 6c 6c 6f 00 00 00 d3 94 01 00 10 00 07 02 // inode:0x194d2=103634 rec_len:16 name_len:5 file_type:1 name:hello // 第三个条目
000030 73 75 62 5f 64 69 72 00 d6 94 01 00 0c 00 04 01 // inode:0x194d3=103635 rec_len:16 name_len:7 file_type:2 name:sub_dir // 第四个条目
000040 74 65 73 74 d9 94 01 00 14 00 0b 01 64 69 72 5f // inode:0x194d6=103638 rec_len:16 name_len:4 file_type:1 name:test // 第五个条目
000050 72 61 72 2e 74 78 74 00 d5 94 01 00 a8 03 07 01 // inode:0x194d9=103641 rec_len:20 name_len:12 file_type:1 name:dir_rar.txt // 第六个条目
000060 64 69 72 5f 72 61 72 77 d7 94 01 00 98 03 10 01 //
000070 2e 64 69 72 5f 72 61 72 2e 74 78 74 2e 73 77 70
000080 d8 94 01 00 80 03 10 01 2e 64 69 72 5f 72 61 72
000090 2e 74 78 74 2e 73 77 78 00 00 00 00 00 00 00 00
0000a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
000400
struct ext2_dir_entry_2 { // 目录条目
  __le32 inode; /* Inode number */
  __le16 rec_len; /* Directory entry length */
  __u8 name_len; /* Name length */
  __u8 file_type;
  char name[]; /* File name, up to EXT2_NAME_LEN */
};
[root@A23320569 raw]# ll -ai
total 7
103633 drwxr-xr-x 3 root root 1024 Jan 8 16:30 .
2 drwxr-xr-x 5 root root 1024 Jan 8 16:00 ..
103637 -rw-r--r-- 1 root root 1024 Jan 8 16:28 dir_rar
103641 -rw-r--r-- 1 root root 614 Jan 8 16:39 dir_rar.txt
103634 -rw-r--r-- 1 root root 13 Jan 8 16:05 hello
103635 drwxr-xr-x 2 root root 1024 Jan 8 16:05 sub_dir
103638 -rw-r--r-- 1 root root 16 Jan 8 16:05 test
inode         rec_len       name_len          file_type        name
103633         12                   1                      2            .
2                   12                    2                     2            . .
103637         16         7      1       dir_rar
103641    20        12        1      dir_rar.txt
103634    16         5         1      hello
103635    16         7            2      sub_dir
103638    12         4       1    test

方法二:通过inode 计算出对应的inode在哪个块,然后获取对应的数据所在的块
raw目录对饮的inode: 103633
一个group有2032个inodes
103633/2032 = 51 位于第51个块组内(inode块号从1开始) 103633/2032 = 51.000492125984251968503937007874,在51个块组内

Group 50: (Blocks 409601-417792)
Block bitmap at 409601 (+0), Inode bitmap at 409602 (+1)
Inode table at 409603-409856 (+2)
7936 free blocks, 2032 free inodes, 0 directories
Free blocks: 409857-417792
Free inodes: 101601-103632 // 对应的是inode 号而不是 所在的block号,并且依次序递增
Group 51: (Blocks 417793-425984)
Block bitmap at 417793 (+0), Inode bitmap at 417794 (+1)
Inode table at 417795-418048 (+2)
7931 free blocks, 2026 free inodes, 2 directories
Free blocks: 418051-418304, 418307-419840, 419842-425984
Free inodes: 103636, 103639-103640, 103642-105664 // 从这个信息可以看出目录文件集中出现在块组 51 里面
Group 52: (Blocks 425985-434176)
Block bitmap at 425985 (+0), Inode bitmap at 425986 (+1)
Inode table at 425987-426240 (+2)
7936 free blocks, 2032 free inodes, 0 directories
Free blocks: 426241-434176
Free inodes: 105665-107696

一个块1024BYTE,一个块有1024/128=8个inode 前面51个块组一共有 103632 inodes
因此在51个块组内第一个inode块里面
// dump出具体的数据:dd if=/dev/loop6 bs=1k skip=417795 count=10 | od -tx1 -Ax > ./new_group51.txt
000000 ed 41 00 00 00 04 00 00 5a 52 53 5a 48 52 53 5a
000010 48 52 53 5a 00 00 00 00 00 00 03 00 02 00 00 00
000020 00 00 00 00 32 00 00 00 01 61 06 00 00 00 00 00
000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
根据struct ext2_inode结构体知道,inode对应文件内容所在block号为第40个偏移的uint类型
struct ext2_inode{
?// 偏移为40个字节
  __u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */ // 15
  __u32 i_generation; /* File version (for NFS) */
  __u32 i_file_acl; /* File ACL */
  __u32 i_dir_acl; /* Directory ACL */
  __u32 i_faddr; /* Fragment address */
  ...
}
知道只有一个直接映射的block块,且对应的块号为:0x66101=418049。这个数据和之前的debugfs得出来的一致!!

参考资料

   1.  linux-2.4内核代码

       2. 《linux内核源代码情景分析》

       3. 《深入linux内核架构》

       4. 《鸟哥的linux私房菜 基础篇》

未完待续