ext4它突出的特点有:数据分段管理、多块分配、延迟分配、持久预分配、日志校验、支持更大的文件系统和文件大小

MTD(Memory Technology Devices)子系统是RAW NandFlash的抽象层,它是Linux系统用来管理NandFlash的,它向Linux系统提供了统一的抽象接口,用于读/写/控制NandFlash。

MTD子系统向用户提供的接口如下:

•/dev/mtd0,/dev/mtd1...,这个是字符设备接口,它提供了NandFlash的I/O操作,ioctl操作等

•sysfs文件系统接口,在这个接口中可以获取到MTD设备的更多,更全的信息

•proc文件系统,历史遗留接口,只提供一些基本的MTD设备信息MTD向内核提供了各种API,供内核更高层级的子系统使用,

比如,文件系统,以及后面要提到的UBI子系统。

一、文件系统结构体介绍

1.1 superblock超级块

superblock的主要内容有:
文件系统信息、块大小和块组信息、Inode 相关信息、文件系统大小和使用情况、日志相关信息、挂载信息、校验和和备份信息

root@OpenWrt:/# hexdump -s 0 -n 4096 -C /dev/block/user_data 
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000400  00 eb 0d 00 f0 9c 37 00  d8 c7 02 00 42 53 36 00  |......7.....BS6.|
00000410  43 ea 0d 00 00 00 00 00  02 00 00 00 02 00 00 00  |C...............|
00000420  00 80 00 00 00 80 00 00  d0 1f 00 00 12 3b 3d 4b  |.............;=K|
00000430  87 b6 41 64 34 00 ff ff  53 ef 01 00 01 00 00 00  |..Ad4...S.......|
00000440  12 3b 3d 4b 00 00 00 00  00 00 00 00 01 00 00 00  |.;=K............|
00000450  00 00 00 00 0b 00 00 00  00 01 00 00 3c 00 00 00  |............<...|
00000460  c2 02 00 00 6b 04 00 00  d9 30 1d ef b3 77 42 b0  |....k....0...wB.|
00000470  99 d4 2f 79 04 52 17 5e  00 00 00 00 00 00 00 00  |../y.R.^........|
00000480  00 00 00 00 00 00 00 00  2f 64 61 74 61 00 00 00  |......../data...|
00000490  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000004c0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 04  |................|
000004d0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000004e0  08 00 00 00 00 00 00 00  00 00 00 00 e2 2b 56 ed  |.............+V.|
000004f0  fb c1 4e 22 8b cb c0 dc  ce e6 e0 10 01 01 40 00  |..N"..........@.|
00000500  0c 00 00 00 00 00 00 00  12 3b 3d 4b 0a f3 01 00  |.........;=K....|
00000510  04 00 00 00 00 00 00 00  00 00 00 00 00 40 00 00  |.............@..|
00000520  03 84 18 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000530  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000540  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 04  |................|
00000550  00 00 00 00 00 00 00 00  00 00 00 00 20 00 20 00  |............ . .|
00000560  02 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000570  00 00 00 00 04 01 00 00  29 1d 00 00 00 00 00 00  |........).......|
00000580  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000007f0  00 00 00 00 00 00 00 00  00 00 00 00 1a 69 2a 09  |.............i*.|
00000800  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00001000

1.2 Group descriptors组描述

在 ext4 文件系统中,Group Descriptor(块组描述符),用于描述和管理文件系统的块组(Block Group)。。Group Descriptor(块组描述符),每个块组包含文件系统中的一部分数据块和 inode,包含了block_bitmap和inode_bitmap和inode_table等

/*
 * 块组描述符的结构
 */
struct ext4_group_desc
{
	__le32	bg_block_bitmap_lo;	/* 块位图块 */
	__le32	bg_inode_bitmap_lo;	/* inode 位图块 */
	__le32	bg_inode_table_lo;	/* inode 表块 */
	__le16	bg_free_blocks_count_lo;/* 空闲块数量 */
	__le16	bg_free_inodes_count_lo;/* 空闲 inode 数量 */
	__le16	bg_used_dirs_count_lo;	/* 目录数量 */
	__le16	bg_flags;		/* EXT4_BG_flags(INODE_UNINIT 等) */
	__le32  bg_exclude_bitmap_lo;   /* 快照排除位图 */
	__le16  bg_block_bitmap_csum_lo;/* crc32c(s_uuid+grp_num+bbitmap) LE */
	__le16  bg_inode_bitmap_csum_lo;/* crc32c(s_uuid+grp_num+ibitmap) LE */
	__le16  bg_itable_unused_lo;	/* 未使用的 inode 数量 */
	__le16  bg_checksum;		/* crc16(sb_uuid+group+desc) */
	__le32	bg_block_bitmap_hi;	/* 块位图块 MSB */
	__le32	bg_inode_bitmap_hi;	/* inode 位图块 MSB */
	__le32	bg_inode_table_hi;	/* inode 表块 MSB */
	__le16	bg_free_blocks_count_hi;/* 空闲块数量 MSB */
	__le16	bg_free_inodes_count_hi;/* 空闲 inode 数量 MSB */
	__le16	bg_used_dirs_count_hi;	/* 目录数量 MSB */
	__le16  bg_itable_unused_hi;    /* 未使用的 inode 数量 MSB */
	__le32  bg_exclude_bitmap_hi;   /* 排除位图块 MSB */
	__le16  bg_block_bitmap_csum_hi;/* crc32c(s_uuid+grp_num+bbitmap) BE */
	__le16  bg_inode_bitmap_csum_hi;/* crc32c(s_uuid+grp_num+ibitmap) BE */
	__u32   bg_reserved;            /* 保留 */
};

group 0 中 Group descriptors 的数据如下:

root@OpenWrt:/# hexdump -s 4096 -n 4096 -C /dev/block/user_data 
00001000  03 04 00 00 13 04 00 00  23 04 00 00 07 5c c4 1f  |........#....\..|
00001010  02 00 04 00 00 00 00 00  47 e8 09 8d c4 1f 5c f5  |........G.....\.|
00001020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00001030  00 00 00 00 00 00 00 00  02 02 08 06 00 00 00 00  |................|
00001040  04 04 00 00 14 04 00 00  20 06 00 00 fc 7b d0 1f  |........ ....{..|
00001050  00 00 05 00 00 00 00 00  40 78 00 00 d0 1f 2f 0f  |........@x..../.|
00001060  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00001070  00 00 00 00 00 00 00 00  1b 87 00 00 00 00 00 00  |................|
00001080  05 04 00 00 15 04 00 00  1d 08 00 00 00 80 d0 1f  |................|
00001090  00 00 07 00 00 00 00 00  00 00 00 00 d0 1f eb 94  |................|
000010a0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000010c0  06 04 00 00 16 04 00 00  1a 0a 00 00 fd 7b d0 1f  |.............{..|
000010d0  00 00 07 00 00 00 00 00  00 00 00 00 d0 1f 95 e2  |................|
000010e0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00001100  07 04 00 00 17 04 00 00  17 0c 00 00 00 80 d0 1f  |................|
00001110  00 00 07 00 00 00 00 00  00 00 00 00 d0 1f a5 b7  |................|
00001120  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*

bg_block_bitmap_lo 03 04 00 00 /* Blocks bitmap block */

bg_inode_bitmap_lo 13 04 00 00 /* Inodes bitmap block */

bg_inode_table_lo 23 04 00 00 /* Inodes table block */

1.3 Block bitmap块位图

Block bitmap 块位图用于管理块组(Block Group)中的数据块,用于跟踪和管理块组内数据块使用情况的重要数据结构。块位图是文件系统的一部分,用于记录文件系统中的每一个数据块是否已经被分配给文件或目录。

bg_block_bitmap_lo 00000403->403000 4206592

查看Block bitmap中的数据

root@OpenWrt:/# hexdump -s 4206592 -n 4096 -C /dev/block/user_data 
00403000  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
*
00403470  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff 01  |................|
00403480  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00404000
root@OpenWrt:/# 

1.4 Inode bitmap索引节点位图

Inode bitmap 是用于管理块组(Block Group)中的inode。用于管理和跟踪块组中inode(索引节点)分配情况的一种关键数据结构。inode是文件系统中用于存储文件和目录元数据的数据结构,包括文件的权限、所有者、大小、修改时间等信息。

bg_inode_bitmap_lo 13 04 00 00 -> 00 00 04 13 413000 4272128

root@OpenWrt:/# hexdump -s 4272128 -n 4096 -C /dev/block/user_data 
00413000  ff 0f 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00413010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
004133f0  00 00 00 00 00 00 00 00  00 00 ff ff ff ff ff ff  |................|
00413400  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
*
00414000
root@OpenWrt:/# 

 1.5 Inode table索引节点表

1.5.1 索引节点介绍

索引节点表是是一个核心数据结构,用于存储文件和目录的元数据。每个文件和目录在文件系统中都有一个对应的inode(索引节点),inode表就是存储这些索引节点的地方。

bg_inode_table_lo 23 04 00 00 -》1059

Inode size:               256:
Inode table at 1059-1567 (+1059)
  • 一个索引节点的大小为256Byte
  • 从 Group 0信息中可以知道Group 0 的索引表位置在1059 块的位置

1.5.2 inode.i_block介绍

inode.i_block 是 ext4 文件系统中 inode 结构的一个重要字段,用于存储文件数据块的指针。它支持直接块和间接块,允许文件系统高效地管理文件的数据位置,支持从小文件到大文件的存储需求。通过 i_block,文件系统能够准确地定位文件数据块,从而实现高效的数据读写操作。

二、通过inode定位到文件block

2.1 查看文件系统信息

其实使用dumpe2fs命令查看的ext4文件系统信息就是从superblock上的数据解析而来。

从dumpe2fs看:

root@OpenWrt:/# ./dumpe2fs /dev/block/user_data 
dumpe2fs 1.45.6 (20-Mar-2020)
Filesystem volume name:   <none>
Last mounted on:          /data
Filesystem UUID:          d9301def-b377-42b0-99d4-2f790452175e
Filesystem magic number:  0xEF53
Filesystem revision #:    1 (dynamic)
Filesystem features:      has_journal ext_attr resize_inode dir_index filetype extent 64bit flex_bg sparse_super large_file huge_file dir_nlink extra_isize metadata_csum
Filesystem flags:         unsigned_directory_hash 
Default mount options:    user_xattr acl
Filesystem state:         clean
Errors behavior:          Continue
Filesystem OS type:       Linux
Inode count:              912128
Block count:              3644656
Reserved block count:     182232
Free blocks:              3560258
Free inodes:              911939
First block:              0
Block size:               4096
Fragment size:            4096
Group descriptor size:    64
Reserved GDT blocks:      1024
Blocks per group:         32768
Fragments per group:      32768
Inodes per group:         8144
Inode blocks per group:   509
Flex block group size:    16
Filesystem created:       Fri Jan  1 00:00:18 2010
Last mount time:          Fri Jan  1 00:00:18 2010
Last write time:          Thu Apr 20 22:02:47 2023
Mount count:              52
Maximum mount count:      -1
Last checked:             Fri Jan  1 00:00:18 2010
Check interval:           0 (<none>)
Lifetime writes:          7465 kB
Reserved blocks uid:      0 (user root)
Reserved blocks gid:      0 (group root)
First inode:              11
Inode size:               256
Required extra isize:     32
Desired extra isize:      32
Journal inode:            8
Default directory hash:   half_md4
Directory Hash Seed:      e22b56ed-fbc1-4e22-8bcb-c0dccee6e010
Journal backup:           inode blocks
Checksum type:            crc32c
Checksum:                 0x092a691a
Journal features:         journal_incompat_revoke journal_64bit journal_checksum_v3
Journal size:             64M
Journal length:           16384
Journal sequence:         0x000001ad
Journal start:            0
Journal checksum type:    crc32c
Journal checksum:         0x5ce2968d


Group 0: (Blocks 0-32767) csum 0xf55c [ITABLE_ZEROED]
  Primary superblock at 0, Group descriptors at 1-2
  Reserved GDT blocks at 3-1026
  Block bitmap at 1027 (+1027), csum 0x0202e847
  Inode bitmap at 1043 (+1043), csum 0x06088d09
  Inode table at 1059-1567 (+1059)
  23559 free blocks, 8132 free inodes, 2 directories, 8132 unused inodes
  Free blocks: 9209-32767
  Free inodes: 13-8144
Group 1: (Blocks 32768-65535) csum 0x0f2f [INODE_UNINIT, ITABLE_ZEROED]
  Backup superblock at 32768, Group descriptors at 32769-32770
  Reserved GDT blocks at 32771-33794
  Block bitmap at 1028 (bg #0 + 1028), csum 0x871b7840
  Inode bitmap at 1044 (bg #0 + 1044), csum 0x00000000
  Inode table at 1568-2076 (bg #0 + 1568)
  31740 free blocks, 8144 free inodes, 0 directories, 8144 unused inodes
  Free blocks: 33796-65535
  Free inodes: 8145-16288

  

该工具通过读取super block获取到各种信息。

2.2 查看索引节点信息

Inode size:               256
Group 0:
Block bitmap at 1027 (+1027), csum 0x0202e847
Inode bitmap at 1043 (+1043), csum 0x06088d09
Inode table at 1059-1567 (+1059)
  • 一个索引节点的大小为256Byte
  • 从 Group 0信息中可以知道Group 0 的索引表位置在1059-1567 块的位置

查看索引节点信息:

1059*4096=4337664

root@OpenWrt:/# hexdump -s 4337664 -n 4096 -C /dev/block/user_data 
00423000  00 00 00 00 00 00 00 00  12 3b 3d 4b 12 3b 3d 4b  |.........;=K.;=K|
00423010  12 3b 3d 4b 00 00 00 00  00 00 00 00 00 00 00 00  |.;=K............|
00423020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00423070  00 00 00 00 00 00 00 00  00 00 00 00 93 0e 00 00  |................|
00423080  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00423100  ed 41 00 00 00 10 00 00  25 b6 79 66 fa cb 78 66  |.A......%.yf..xf|
00423110  fa cb 78 66 00 00 00 00  00 00 09 00 08 00 00 00  |..xf............|
00423120  00 00 08 00 0b 00 00 00  0a f3 01 00 04 00 00 00  |................|
00423130  00 00 00 00 00 00 00 00  01 00 00 00 f3 23 00 00  |.............#..|
00423140  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00423170  00 00 00 00 00 00 00 00  00 00 00 00 71 69 00 00  |............qi..|
00423180  20 00 ce 62 bc ff be 80  bc ff be 80 60 d8 e4 a6  | ..b........`...|
00423190  12 3b 3d 4b 00 00 00 00  00 00 00 00 00 00 00 00  |.;=K............|
004231a0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00423270  00 00 00 00 00 00 00 00  00 00 00 00 ec 54 00 00  |.............T..|
00423280  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00423370  00 00 00 00 00 00 00 00  00 00 00 00 06 f3 00 00  |................|
00423380  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00423470  00 00 00 00 00 00 00 00  00 00 00 00 48 c9 00 00  |............H...|
00423480  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00423570  00 00 00 00 00 00 00 00  00 00 00 00 9a 87 00 00  |................|
00423580  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00423600  80 81 00 00 00 c0 40 00  12 3b 3d 4b 12 3b 3d 4b  |......@..;=K.;=K|
00423610  12 3b 3d 4b 00 00 00 00  00 00 01 00 08 40 01 00  |.;=K.........@..|
00423620  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00423650  00 00 00 00 00 00 00 00  00 00 00 00 f8 23 00 00  |.............#..|
00423660  00 00 00 00 00 00 00 00  00 00 00 00 01 00 00 00  |................|
00423670  00 00 00 00 00 00 00 00  00 00 00 00 f6 11 00 00  |................|
00423680  20 00 02 cd 00 00 00 00  00 00 00 00 00 00 00 00  | ...............|
00423690  12 3b 3d 4b 00 00 00 00  00 00 00 00 00 00 00 00  |.;=K............|
004236a0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00423700  80 81 00 00 00 00 00 04  13 3b 3d 4b 12 3b 3d 4b  |.........;=K.;=K|
00423710  12 3b 3d 4b 00 00 00 00  00 00 01 00 00 00 02 00  |.;=K............|
00423720  00 00 08 00 00 00 00 00  0a f3 01 00 04 00 00 00  |................|
00423730  00 00 00 00 00 00 00 00  00 40 00 00 03 84 18 00  |.........@......|
00423740  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00423770  00 00 00 00 00 00 00 00  00 00 00 00 f7 39 00 00  |.............9..|
00423780  20 00 e0 4c 00 00 00 00  00 00 00 00 00 00 00 00  | ..L............|
00423790  13 3b 3d 4b 00 00 00 00  00 00 00 00 00 00 00 00  |.;=K............|
004237a0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00423870  00 00 00 00 00 00 00 00  00 00 00 00 00 f2 00 00  |................|
00423880  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00423970  00 00 00 00 00 00 00 00  00 00 00 00 d2 bc 00 00  |................|
00423980  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00423a00  c0 41 00 00 00 40 00 00  25 b6 79 66 12 3b 3d 4b  |.A...@..%.yf.;=K|
00423a10  12 3b 3d 4b 00 00 00 00  00 00 02 00 20 00 00 00  |.;=K........ ...|
00423a20  00 00 08 00 00 00 00 00  0a f3 01 00 04 00 00 00  |................|
00423a30  00 00 00 00 00 00 00 00  04 00 00 00 f4 23 00 00  |.............#..|
00423a40  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00423a70  00 00 00 00 00 00 00 00  00 00 00 00 1c aa 00 00  |................|
00423a80  20 00 7c 1f 00 00 00 00  00 00 00 00 60 d8 e4 a6  | .|.........`...|
00423a90  12 3b 3d 4b 00 00 00 00  00 00 00 00 00 00 00 00  |.;=K............|
00423aa0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00423b00  a4 81 00 00 d6 00 00 00  fa cb 78 66 04 cc 78 66  |..........xf..xf|
00423b10  04 cc 78 66 00 00 00 00  00 00 01 00 08 00 00 00  |..xf............|
00423b20  00 00 08 00 01 00 00 00  0a f3 01 00 04 00 00 00  |................|
00423b30  00 00 00 00 00 00 00 00  01 00 00 00 03 84 00 00  |................|
00423b40  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00423b60  00 00 00 00 86 4e 1d 8f  00 00 00 00 00 00 00 00  |.....N..........|
00423b70  00 00 00 00 00 00 00 00  00 00 00 00 15 3c 00 00  |.............<..|
00423b80  20 00 7e 18 bc e1 39 1a  bc e1 39 1a bc ff be 80  | .~...9...9.....|
00423b90  fa cb 78 66 bc ff be 80  00 00 00 00 00 00 00 00  |..xf............|
00423ba0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00424000
root@OpenWrt:/# 

root@OpenWrt:/data# ls -li
 130305 drwx------    2 root     root          4096 Jan  1  2010 ccci_cfg
 521217 drwxrwxr-x    2 root     root          4096 Apr 21 21:35 connsyslog
 651521 drwxrwxr-x    3 root     root          4096 Apr 17 13:15 debuglog
     13 -rw-r--r--    1 root     root            23 Apr 21 21:37 hello_heath.txt
 260609 drwxr-xr-x    2 root     root          4096 Apr 17 13:15 lbs
 130306 drwxr-xr-x    3 root     root          4096 Apr 17 13:17 log
     12 -rw-r--r--    1 root     root           214 Jun 24  2024 log.pcap
     11 drwx------    2 root     root         16384 Jan  1  2010 lost+found
 651522 drwxrwxr-x    3 root     root          4096 Apr 17 13:15 mdlog
root@OpenWrt:/data# 

如果是其他目录要经过计算找到对应的Group组,要知道Group的size,.然后除以size,得到就是Group 号,

然后在对应的里找对应inode table

一个文件系统中某个 inode(索引节点)所在的块组 (block group) 以及 inode 在块组中的索引

group = (inode_number - 1) / inodes_per_group

在 Ext2/Ext3/Ext4 文件系统中,数据和元数据(包括 inode)被划分为若干块组。每个块组包含一定数量的 inode 和数据块。将 inode 组织成块组可以提高文件系统的性能和管理效率。

  • inode_number: inode 是存储文件元数据的结构体,每个文件或目录都由一个 inode 表示。inode_number 是某个文件或目录的 inode 编号。
  • inodes_per_group: 每个块组中包含的 inode 数量。
  • group: 表示 inode 所在的块组编号。

公式解释

块组计算公式:

  1. group = (inode_number - 1) / inodes_per_group

这个公式用于确定给定的 inode 编号属于哪个块组。

块组内的 inode 索引计算:

  1. inode_index=(inode_number−1)%inodes_per_group

这个公式用于确定 inode 在块组内的索引位置。

hello_heath.txt文件的Inode号为13

group=12/8144≈0

inode_index=(13−1)%8144 =12

这表明 inode 编号 13 位于第 0 个块组,并且是该块组中的第 13 个 inode(因为索引从 0 开始,所以 12 表示第 13 个 inode)。

计算地址:

1059 * 4096 +(13-1)*256 = 4,337,664 + 3072 = 4340736 = 0x423C00

2.3 定位ext4_inode位置

在 Unix 和 Linux 系统中,当使用 ls -li 命令时,列出的 inode 号是从 1 开始的,而不是从 0 开始。这是因为:

  • Inode 编号从 1 开始: 文件系统中第一个有效的 inode 通常编号为 1。Inode 0 通常被保留并且不用于普通文件或目录的存储。因此,当你看到 ls -li 输出时,所有列出的 inode 编号都是从 1 开始的。

定位到索引ext4_inode所在的位置:

1059 * 4096 +(13-1)*256 = 4,337,664 + 3072 = 4340736 = 0x423C00
root@OpenWrt:/data# hexdump -s 4340736 -n 4096 -C /dev/block/user_data 
00423c00  a4 81 00 00 17 00 00 00  10 02 43 64 1a 02 43 64  |..........Cd..Cd|
00423c10  1a 02 43 64 00 00 00 00  00 00 01 00 08 00 00 00  |..Cd............|
00423c20  00 00 08 00 01 00 00 00  0a f3 01 00 04 00 00 00  |................|
00423c30  00 00 00 00 00 00 00 00  01 00 00 00 01 86 00 00  |................|
00423c40  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00423c60  00 00 00 00 7a b0 de 61  00 00 00 00 00 00 00 00  |....z..a........|
00423c70  00 00 00 00 00 00 00 00  00 00 00 00 a2 70 00 00  |.............p..|
00423c80  20 00 3c 32 1c c4 22 64  1c c4 22 64 18 c4 22 64  | .<2.."d.."d.."d|
00423c90  10 02 43 64 18 c4 22 64  00 00 00 00 00 00 00 00  |..Cd.."d........|
00423ca0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00423d00  a4 81 00 00 00 00 00 00  12 02 43 64 21 02 43 64  |..........Cd!.Cd|
00423d10  21 02 43 64 21 02 43 64  00 00 00 00 00 00 00 00  |!.Cd!.Cd........|
00423d20  00 00 08 00 01 00 00 00  0a f3 00 00 04 00 00 00  |................|
00423d30  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00423d60  00 00 00 00 7a 7f b6 04  00 00 00 00 00 00 00 00  |....z...........|
00423d70  00 00 00 00 00 00 00 00  00 00 00 00 cc b9 00 00  |................|
00423d80  20 00 7a de 20 ee 97 79  20 ee 97 79 1c b2 ba dd  | .z. ..y ..y....|
00423d90  12 02 43 64 1c b2 ba dd  00 00 00 00 00 00 00 00  |..Cd............|
00423da0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00424c00

2.4 i_block的数据解析

fs/ext4/ext4_extents.h

quectel/ext_kernel-5.4/fs/ext4/ext4.h

ext4_inode成员i_block

struct ext4_inode {
	__le16	i_mode;		/* File mode */
	__le16	i_uid;		/* Low 16 bits of Owner Uid */
	__le32	i_size_lo;	/* Size in bytes */
	__le32	i_atime;	/* Access time */
	__le32	i_ctime;	/* Inode Change time */
	__le32	i_mtime;	/* Modification time */
	__le32	i_dtime;	/* Deletion Time */
	__le16	i_gid;		/* Low 16 bits of Group Id */
	__le16	i_links_count;	/* Links count */
	__le32	i_blocks_lo;	/* Blocks count */
	__le32	i_flags;	/* File flags */
	union {
		struct {
			__le32  l_i_version;
		} linux1;
		struct {
			__u32  h_i_translator;
		} hurd1;
		struct {
			__u32  m_i_reserved1;
		} masix1;
	} osd1;				/* OS dependent 1 */
	__le32	i_block[EXT4_N_BLOCKS];/* Pointers to blocks */
	__le32	i_generation;	/* File version (for NFS) */
	__le32	i_file_acl_lo;	/* File ACL */
	__le32	i_size_high;
	__le32	i_obso_faddr;	/* Obsoleted fragment address */
  	union {
		struct {
			__le16	l_i_blocks_high; /* were l_i_reserved1 */
			__le16	l_i_file_acl_high;
			__le16	l_i_uid_high;	/* these 2 fields */
			__le16	l_i_gid_high;	/* were reserved2[0] */
			__le16	l_i_checksum_lo;/* crc32c(uuid+inum+inode) LE */
			__le16	l_i_reserved;
		} linux2;
		struct {
			__le16	h_i_reserved1;	/* Obsoleted fragment number/size which are removed in ext4 */
			__u16	h_i_mode_high;
			__u16	h_i_uid_high;
			__u16	h_i_gid_high;
			__u32	h_i_author;
		} hurd2;
		struct {
			__le16	h_i_reserved1;	/* Obsoleted fragment number/size which are removed in ext4 */
			__le16	m_i_file_acl_high;
			__u32	m_i_reserved2[2];
		} masix2;
	} osd2;				/* OS dependent 2 */
	__le16	i_extra_isize;
	__le16	i_checksum_hi;	/* crc32c(uuid+inum+inode) BE */
	__le32  i_ctime_extra;  /* extra Change time      (nsec << 2 | epoch) */
	__le32  i_mtime_extra;  /* extra Modification time(nsec << 2 | epoch) */
	__le32  i_atime_extra;  /* extra Access time      (nsec << 2 | epoch) */
	__le32  i_crtime;       /* File Creation time */
	__le32  i_crtime_extra; /* extra FileCreationtime (nsec << 2 | epoch) */
	__le32  i_version_hi;	/* high 32 bits for 64-bit version */
	__le32	i_projid;	/* Project ID */
};

i_block 对ext4_inode的偏移量是0x28(十进制40 可以从ext4_inode结构看出),对i_block的数据进行解析:

/*
 * ext4_inode has i_block array (60 bytes total).
 * The first 12 bytes store ext4_extent_header;
 * the remainder stores an array of ext4_extent.
 * For non-inode extent blocks, ext4_extent_tail
 * follows the array.
 */

/*
 * ext4_inode 有一个 i_block 数组(总共 60 字节)。
 * 前 12 字节存储 ext4_extent_header;
 * 其余部分存储一个 ext4_extent 数组。
 * 对于非 inode 的 extent 块,ext4_extent_tail
 * 跟在数组后面。
 */
/*
 * Each block (leaves and indexes), even inode-stored has header.
 */
struct ext4_extent_header {
    __le16  eh_magic;   /* 魔数,可能用于支持不同的格式 */
    __le16  eh_entries; /* 有效条目的数量 */
    __le16  eh_max;     /* 条目存储的容量 */
    __le16  eh_depth;   /* 表示是否有实际底层块 */
    __le32  eh_generation;  /* 树的代数 */
};


4x2+4=12往下偏移12 即ext4_extent.结构体,该结构体比较重要,物理块地址是找到存数据内容的关键。

struct ext4_extent {
    __le32  ee_block;   /* 该 extent 覆盖的第一个逻辑块 */
    __le16  ee_len;     /* 该 extent 覆盖的块数 */
    __le16  ee_start_hi;    /* 物理块地址的高 16 位 */
    __le32  ee_start_lo;    /* 物理块地址的低 32 位 */
};

ext4_extent 第一个逻辑块映射的物理块地址(即是数据内容)

0a f3 -> F3 0A >

offset 数据

0x0C ee_block 00 00 00 00

0x10 ee_len 00 01

0x12 ee_start_hi 00 00

0x14 ee_start_lo 01 86 00 00 00 00 86 01

0X8601 34305 34305 *4096=140513280 8601000

f1 1f 08 00 00081FF1 532465*4096=2180976640

2.5 比较数据

第一个逻辑块映射的物理块地址ee_start_lo(即是数据内容):

root@OpenWrt:/data# hexdump -s 140513280 -n 4096 -C /dev/block/user_data 
08601000  68 65 6c 6c 6f 20 68 65  61 74 68 20 74 65 73 74  |hello heath test|
08601010  20 65 78 74 34 21 0a 00  00 00 00 00 00 00 00 00  | ext4!..........|
08601020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
08602000
root@OpenWrt:/data# 

原始文件数据:

root@OpenWrt:/data#  hexdump -s 0 -n 4096 -C hello_heath.txt 
00000000  68 65 6c 6c 6f 20 68 65  61 74 68 20 74 65 73 74  |hello heath test|
00000010  20 65 78 74 34 21 0a                              | ext4!.|
00000017
root@OpenWrt:/data# 

2.6 根目录查询

根目录的inode是2

如果是其他目录要经过计算找到对应的Group组,要知道Group的size,.然后除以size,得到就是Group 号,然后在对应的里找对应inode table。一个文件系统中某个 inode(索引节点)所在的块组 (block group) 以及 inode 在块组中的索引

group = (inode_number - 1) / inodes_per_group

在 Ext2/Ext3/Ext4 文件系统中,数据和元数据(包括 inode)被划分为若干块组。每个块组包含一定数量的 inode 和数据块。将 inode 组织成块组可以提高文件系统的性能和管理效率。

  • inode_number: inode 是存储文件元数据的结构体,每个文件或目录都由一个 inode 表示。inode_number 是某个文件或目录的 inode 编号。
  • inodes_per_group: 每个块组中包含的 inode 数量。
  • group: 表示 inode 所在的块组编号。

公式解释

块组计算公式:

  1. group = (inode_number - 1) / inodes_per_group

这个公式用于确定给定的 inode 编号属于哪个块组。

块组内的 inode 索引计算:

  1. inode_index=(inode_number−1)%inodes_per_group

这个公式用于确定 inode 在块组内的索引位置。

Inodes per group:         8144
 130306 drwxr-xr-x    3 root     root          4096 Apr 17 13:17 log

/*下面分析log目录*/
group = (inode_number - 1) / inodes_per_group
16=(130306-1)/8144
     (130306-1)%8144=1
     
这表示 inode 编号 130306 是第 16 个块组的第 2 个 inode(因为索引从 0 开始)。

  Group 16: (Blocks 524288-557055) csum 0xa61e [ITABLE_ZEROED]
  Block bitmap at 524288 (+0), csum 0x4fcbcb33
  Inode bitmap at 524304 (+16), csum 0x30b7abd7
  Inode table at 524320-524828 (+32)
  24584 free blocks, 8124 free inodes, 8 directories, 8090 unused inodes
  Free blocks: 532467-532468, 532474-557055
  Free inodes: 130308, 130310, 130312, 130317-130342, 130346-130347, 130350, 130353, 130356, 130359-138448

/****************/
ext4_inode
524320*4096+1*256=2147614976

root@OpenWrt:/# hexdump -s 2147614976  -n 256 -C /dev/block/user_data 
80020100  ed 41 00 00 00 10 00 00  25 b6 79 66 fe 46 3d 64  |.A......%.yf.F=d|
80020110  fe 46 3d 64 00 00 00 00  00 00 03 00 08 00 00 00  |.F=d............|
80020120  00 00 08 00 02 00 00 00  0a f3 01 00 04 00 00 00  |................|
80020130  00 00 00 00 00 00 00 00  01 00 00 00 f1 1f 08 00  |................|
80020140  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
80020160  00 00 00 00 a9 54 0e 43  00 00 00 00 00 00 00 00  |.....T.C........|
80020170  00 00 00 00 00 00 00 00  00 00 00 00 51 e8 00 00  |............Q...|
80020180  20 00 6e bb 14 7a 1e c1  14 7a 1e c1 60 d8 e4 a6  | .n..z...z..`...|
80020190  fe 46 3d 64 14 7a 1e c1  00 00 00 00 00 00 00 00  |.F=d.z..........|
800201a0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
80020200
root@OpenWrt:/# 

/****************/
ext4_extent->ee_start_lo
f1 1f 08 00->00081FF1
532465x4096=2180976640

root@OpenWrt:/# hexdump -s 2180976640  -n 256 -C /dev/block/user_data 
81ff1000  02 fd 01 00 0c 00 01 02  2e 00 00 00 02 00 00 00  |................|
81ff1010  0c 00 02 02 2e 2e 00 00  03 fd 01 00 dc 0f 07 02  |................|
81ff1020  61 65 65 5f 65 78 70 00  00 00 00 00 00 00 00 00  |aee_exp.........|
81ff1030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
81ff1100
root@OpenWrt:/# 
root@OpenWrt:/# cd data/log/
root@OpenWrt:/data/log# ls
aee_exp
root@OpenWrt:/data/log# 
      

三、制作ext4文件系统镜像

3.1 ext4文件系统镜像

3.1.1 生成一个空的512MiB文件

dd if=/dev/zero of=rootfs.ext4 bs=1024 count=524288 (指定每一块大小为1024字节,一共有524288块,那么就是524288 * 1024 B = 512MiB)

3.1.2 对生成的文件进行格式化

mkfs.ext4 rootfs.ext4

3.1.3 挂载此空镜像

mount -o loop rootfs.ext4 /mnt/rootfs

3.1.4 向挂载好的文件系统中写入需要加入的文件

cp everyfile /mnt/rootfs

3.1.5 卸载根文件系统

umount /mnt/rootfs

3.1.6 将镜像写入sd卡的某个分区中

dd if=rootfs.ext4 of=/dev/mmcblk0p3

3.1.7 此时挂载一下某分区即可在发现刚才复制进去的文件

如果你需要将一个预先配置好的文件系统镜像写入设备,dd 是合适的选择。如果你需要一个新的空文件系统,mkfs.ext4 是合适的选择。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐