linux ext2文件系统浅析

前言

网上关于ext2文件系统的博客有很多,但看完之后还是有些云里雾里,于是我分析了一下数据结构和文件系统镜像二进制数据
【为了避免排版混乱,我引用了很多代码块标签,因为markdown会自动处理掉多的空格等符号】

ext2内容概述

第一部分 super block
第二部分 group_desc
第三部分 block_bitmap
第四部分 inode_bitmap
第五部分 inode_table
第六部分 dir entry
第七部分 data区
第八部分 间接块
第九部分 块组

实验准备

e2progfs源码下载地址
https://sourceforge.net/projects/e2fsprogs/

创建文件系统脚本
create_ext2img.sh

umount mnt
dd if=/dev/zero of=ext2.img bs=1024 count=128
mke2fs -t ext2 ext2.img -b 1024
hexdump -Cv ext2.img > 00.hex

创建几个制定大小文件脚本
make_files.sh

# 需要一个超多字符1的文件c1
# 只需改动bs即可改变目标文件大小
dd if=c1 of=file1 bs=16384 count=1
cp file1 file2
cp file1 file3
cp file1 file4
cp file1 file5
sed -i 's/1/2/g' file2
sed -i 's/1/3/g' file3
sed -i 's/1/4/g' file4
sed -i 's/1/5/g' file5

写入文件并导出2进制数据

mount ext2.img mnt
cp file1 mnt
cp file2 mnt
cp file3 mnt
cp file4 mnt
cp file5 mnt
umount mnt
hexdump -Cv ext2.img > f5.hex

二进制对比分析

以下是格式化完成之后 和按脚本操作写入文件之后的二进制对比

1 super block

超级块结构体定义

struct ext2_super_block {
/*000*/	__u32	s_inodes_count;		/* Inodes count */
	__u32	s_blocks_count;		/* Blocks count */
	__u32	s_r_blocks_count;	/* Reserved blocks count */
	__u32	s_free_blocks_count;	/* Free blocks count */
/*010*/	__u32	s_free_inodes_count;	/* Free inodes count */
	__u32	s_first_data_block;	/* First Data Block */
	__u32	s_log_block_size;	/* Block size */
	__u32	s_log_cluster_size;	/* Allocation cluster size */
/*020*/	__u32	s_blocks_per_group;	/* # Blocks per group */
	__u32	s_clusters_per_group;	/* # Fragments per group */
	__u32	s_inodes_per_group;	/* # Inodes per group */
	__u32	s_mtime;		/* Mount time */
/*030*/	__u32	s_wtime;		/* Write time */
	__u16	s_mnt_count;		/* Mount count */
	__s16	s_max_mnt_count;	/* Maximal mount count */
	__u16	s_magic;		/* Magic signature */
	__u16	s_state;		/* File system state */
	__u16	s_errors;		/* Behaviour when detecting errors */
	__u16	s_minor_rev_level;	/* minor revision level */
/*040*/	__u32	s_lastcheck;		/* time of last check */
	__u32	s_checkinterval;	/* max. time between checks */
	__u32	s_creator_os;		/* OS */
	__u32	s_rev_level;		/* Revision level */
/*050*/	__u16	s_def_resuid;		/* Default uid for reserved blocks */
	__u16	s_def_resgid;		/* Default gid for reserved blocks */
	__u32	s_first_ino;		/* First non-reserved inode */
	__u16   s_inode_size;		/* size of inode structure */
	__u16	s_block_group_nr;	/* block group # of this superblock */
	__u32	s_feature_compat;	/* compatible feature set */
/*060*/	__u32	s_feature_incompat;	/* incompatible feature set */
	__u32	s_feature_ro_compat;	/* readonly-compatible feature set */
/*068*/	__u8	s_uuid[16] __nonstring;		/* 128-bit uuid for volume */
/*078*/	__u8	s_volume_name[EXT2_LABEL_LEN] __nonstring;	/* volume name, no NUL? */
/*088*/	__u8	s_last_mounted[64] __nonstring;	/* directory last mounted on, no NUL? */
/*0c8*/	__u32	s_algorithm_usage_bitmap; /* For compression */
	__u8	s_prealloc_blocks;	/* Nr of blocks to try to preallocate*/
	__u8	s_prealloc_dir_blocks;	/* Nr to preallocate for dirs */
	__u16	s_reserved_gdt_blocks;	/* Per group table for online growth */
/*0d0*/	__u8	s_journal_uuid[16] __nonstring;	/* uuid of journal superblock */
/*0e0*/	__u32	s_journal_inum;		/* inode number of journal file */
	__u32	s_journal_dev;		/* device number of journal file */
	__u32	s_last_orphan;		/* start of list of inodes to delete */
/*0ec*/	__u32	s_hash_seed[4];		/* HTREE hash seed */
/*0fc*/	__u8	s_def_hash_version;	/* Default hash version to use */
	__u8	s_jnl_backup_type;	/* Default type of journal backup */
	__u16	s_desc_size;		/* Group desc. size: INCOMPAT_64BIT */
/*100*/	__u32	s_default_mount_opts;	/* default EXT2_MOUNT_* flags used */
	__u32	s_first_meta_bg;	/* First metablock group */
	__u32	s_mkfs_time;		/* When the filesystem was created */
/*10c*/	__u32	s_jnl_blocks[17];	/* Backup of the journal inode */
/*150*/	__u32	s_blocks_count_hi;	/* Blocks count high 32bits */
	__u32	s_r_blocks_count_hi;	/* Reserved blocks count high 32 bits*/
	__u32	s_free_blocks_hi;	/* Free blocks count */
	__u16	s_min_extra_isize;	/* All inodes have at least # bytes */
	__u16	s_want_extra_isize;	/* New inodes should reserve # bytes */
/*160*/	__u32	s_flags;		/* Miscellaneous flags */
	__u16	s_raid_stride;		/* RAID stride in blocks */
	__u16	s_mmp_update_interval;  /* # seconds to wait in MMP checking */
	__u64	s_mmp_block;		/* Block for multi-mount protection */
/*170*/	__u32	s_raid_stripe_width;	/* blocks on all data disks (N*stride)*/
	__u8	s_log_groups_per_flex;	/* FLEX_BG group size */
	__u8	s_checksum_type;	/* metadata checksum algorithm */
	__u8	s_encryption_level;	/* versioning level for encryption */
	__u8	s_reserved_pad;		/* Padding to next 32bits */
	__u64	s_kbytes_written;	/* nr of lifetime kilobytes written */
/*180*/	__u32	s_snapshot_inum;	/* Inode number of active snapshot */
	__u32	s_snapshot_id;		/* sequential ID of active snapshot */
	__u64	s_snapshot_r_blocks_count; /* active snapshot reserved blocks */
/*190*/	__u32	s_snapshot_list;	/* inode number of disk snapshot list */
#define EXT4_S_ERR_START ext4_offsetof(struct ext2_super_block, s_error_count)
	__u32	s_error_count;		/* number of fs errors */
	__u32	s_first_error_time;	/* first time an error happened */
	__u32	s_first_error_ino;	/* inode involved in first error */
/*1a0*/	__u64	s_first_error_block;	/* block involved in first error */
	__u8	s_first_error_func[32] __nonstring;	/* function where error hit, no NUL? */
/*1c8*/	__u32	s_first_error_line;	/* line number where error happened */
	__u32	s_last_error_time;	/* most recent time of an error */
/*1d0*/	__u32	s_last_error_ino;	/* inode involved in last error */
	__u32	s_last_error_line;	/* line number where error happened */
	__u64	s_last_error_block;	/* block involved of last error */
/*1e0*/	__u8	s_last_error_func[32] __nonstring;	/* function where error hit, no NUL? */
#define EXT4_S_ERR_END ext4_offsetof(struct ext2_super_block, s_mount_opts)
/*200*/	__u8	s_mount_opts[64] __nonstring;	/* default mount options, no NUL? */
/*240*/	__u32	s_usr_quota_inum;	/* inode number of user quota file */
	__u32	s_grp_quota_inum;	/* inode number of group quota file */
	__u32	s_overhead_clusters;	/* overhead blocks/clusters in fs */
/*24c*/	__u32	s_backup_bgs[2];	/* If sparse_super2 enabled */
/*254*/	__u8	s_encrypt_algos[4];	/* Encryption algorithms in use  */
/*258*/	__u8	s_encrypt_pw_salt[16];	/* Salt used for string2key algorithm */
/*268*/	__le32	s_lpf_ino;		/* Location of the lost+found inode */
	__le32  s_prj_quota_inum;	/* inode for tracking project quota */
/*270*/	__le32	s_checksum_seed;	/* crc32c(orig_uuid) if csum_seed set */
/*274*/	__u8	s_wtime_hi;
	__u8	s_mtime_hi;
	__u8	s_mkfs_time_hi;
	__u8	s_lastcheck_hi;
	__u8	s_first_error_time_hi;
	__u8	s_last_error_time_hi;
	__u8	s_first_error_errcode;
	__u8    s_last_error_errcode;
/*27c*/ __le16	s_encoding;		/* Filename charset encoding */
	__le16	s_encoding_flags;	/* Filename charset encoding flags */
	__le32  s_orphan_file_inum;	/* Inode for tracking orphan inodes */
	__le32	s_reserved[94];		/* Padding to the end of the block */
/*3fc*/	__u32	s_checksum;		/* crc32c(superblock) */
};

部分二进制对比

00:
00000400  10 00 00 00 80 00 00 00  06 00 00 00 6b 00 00 00  |............k...|
00000410  05 00 00 00 01 00 00 00  00 00 00 00 00 00 00 00  |................|
00000420  00 20 00 00 00 20 00 00  10 00 00 00 00 00 00 00  |. ... ..........|
00000430  10 73 89 66 00 00 ff ff  53 ef 01 00 01 00 00 00  |.s.f....S.......|
00000440  10 73 89 66 00 00 00 00  00 00 00 00 01 00 00 00  |.s.f............|
00000450  00 00 00 00 0b 00 00 00  80 00 00 00 38 00 00 00  |............8...|
f5:
00000400  10 00 00 00 80 00 00 00  06 00 00 00 16 00 00 00  |................|
00000410  00 00 00 00 01 00 00 00  00 00 00 00 00 00 00 00  |................|
00000420  00 20 00 00 00 20 00 00  10 00 00 00 13 73 89 66  |. ... .......s.f|
00000430  13 73 89 66 01 00 ff ff  53 ef 01 00 01 00 00 00  |.s.f....S.......|
00000440  10 73 89 66 00 00 00 00  00 00 00 00 01 00 00 00  |.s.f............|
00000450  00 00 00 00 0b 00 00 00  80 00 00 00 38 00 00 00  |............8...|

super block从磁盘的第1000个字节开始,前面的留给MBR什么启动分区使用

部分数据含义:
inode总数 16个
0x400 s_inodes_count = 0x10;

块总数 128个
0x404 s_blocks_count = 0x80;

保留块总数 6个
0x408 s_r_blocks_count = 0x06;

空闲块总数 从107个变成了22个(df可看)
0x40c s_free_blocks_count = 0x6b -> 0x16;

空闲inode数 刚格式化完是5个,写了5个文件就没有了
0x410 s_free_inodes_count = 0x05 -> 0x00;

每个块组拥有的块数
0x420 s_blocks_per_group = 0x2000;

inode大小 为128字节(有的环境是256字节)
0x458 s_inode_size = 0x80;

2 group desc

struct ext2_group_desc
{
	__u32	bg_block_bitmap;	/* Blocks bitmap block */
	__u32	bg_inode_bitmap;	/* Inodes bitmap block */
	__u32	bg_inode_table;		/* Inodes table block */
	__u16	bg_free_blocks_count;	/* Free blocks count */
	__u16	bg_free_inodes_count;	/* Free inodes count */
	__u16	bg_used_dirs_count;	/* Directories count */
	__u16	bg_flags;
	__u32	bg_exclude_bitmap_lo;	/* Exclude bitmap for snapshots */
	__u16	bg_block_bitmap_csum_lo;/* crc32c(s_uuid+grp_num+bitmap) LSB */
	__u16	bg_inode_bitmap_csum_lo;/* crc32c(s_uuid+grp_num+bitmap) LSB */
	__u16	bg_itable_unused;	/* Unused inodes count */
	__u16	bg_checksum;		/* crc16(s_uuid+group_num+group_desc)*/
};

group desc紧随super block之后
如果第一个文件系统的块大小为1024,那么group desc位于第二个块,否则位于第一个块
【解释:如果super block为1k大小,如果块大小不为1024,那就是2048或4096,这样第一个块就可以同时装下super block和group desc】

00:
00000800  03 00 00 00 04 00 00 00  05 00 00 00 6b 00 05 00  |............k...|
f5:
00000800  03 00 00 00 04 00 00 00  05 00 00 00 16 00 00 00  |................|

部分数据含义:

块位图所在的块编号 3,所以块位图在第3个块,从0xc00开始
0x800 bg_block_bitmap = 0x03;

inode位图所在的块编号 4,所以inode位图在第4个块,从0x1000开始
0x804 bg_inode_bitmap = 0x04;

inode表所在的块编号 5,所以inode位图在第5个块,从0x1400开始
0x808 bg_inode_table = 0x05;

0x80c bg_free_blocks_count = 0x69 -> 0x14;

0x80e bg_free_inodes_count = 0x05 -> 0x00;

3 block bitmap

这部分没啥好说的,就是bitmap

00:
00000c00  ff ff 0f 00 00 00 00 00  00 00 00 00 00 00 00 80  |................|
f5:
00000c00  ff ff ff ff ff ff ff ff  ff 03 00 00 ff ff ff ff  |................|

4 inode bitmap

一样

00:
00001000  ff 07 ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
f5:
00001000  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|

5 inode_table

inode的size在super block中可以查看,这里是128字节

struct ext2_inode_large {
/*00*/	__u16	i_mode;		/* File mode */
	__u16	i_uid;		/* Low 16 bits of Owner Uid */
	__u32	i_size;		/* Size in bytes */
	__u32	i_atime;	/* Access time */
	__u32	i_ctime;	/* Inode Change time */
/*10*/	__u32	i_mtime;	/* Modification time */
	__u32	i_dtime;	/* Deletion Time */
	__u16	i_gid;		/* Low 16 bits of Group Id */
	__u16	i_links_count;	/* Links count */
	__u32	i_blocks;	/* Blocks count */
/*20*/	__u32	i_flags;	/* File flags */
	union {
		struct {
			__u32	l_i_version; /* was l_i_reserved1 */
		} linux1;
		struct {
			__u32  h_i_translator;
		} hurd1;
	} osd1;				/* OS dependent 1 */
/*28*/	__u32	i_block[15];/* Pointers to blocks */
/*64*/	__u32	i_generation;	/* File version (for NFS) */
	__u32	i_file_acl;	/* File ACL */
	__u32	i_size_high;
/*70*/	__u32	i_faddr;	/* Fragment address */
	union {
		struct {
			__u16	l_i_blocks_hi;
			__u16	l_i_file_acl_high;
			__u16	l_i_uid_high;	/* these 2 fields    */
			__u16	l_i_gid_high;	/* were reserved2[0] */
			__u16	l_i_checksum_lo; /* crc32c(uuid+inum+inode) */
			__u16	l_i_reserved;
		} linux2;
		struct {
			__u8	h_i_frag;	/* Fragment number */
			__u8	h_i_fsize;	/* Fragment size */
			__u16	h_i_mode_high;
			__u16	h_i_uid_high;
			__u16	h_i_gid_high;
			__u32	h_i_author;
		} hurd2;
	} osd2;				/* OS dependent 2 */
/*80*/	__u16	i_extra_isize;
	__u16	i_checksum_hi;	/* crc32c(uuid+inum+inode) */
	__u32	i_ctime_extra;	/* extra Change time (nsec << 2 | epoch) */
	__u32	i_mtime_extra;	/* extra Modification time (nsec << 2 | epoch) */
	__u32	i_atime_extra;	/* extra Access time (nsec << 2 | epoch) */
/*90*/	__u32	i_crtime;	/* File creation time */
	__u32	i_crtime_extra;	/* extra File creation time (nsec << 2 | epoch)*/
	__u32	i_version_hi;	/* high 32 bits for 64-bit version */
/*9c*/	__u32   i_projid;       /* Project ID */
};

inode 1

不知道干啥的,没有块指针

00001400  00 00 00 00 00 00 00 00  10 73 89 66 10 73 89 66  |.........s.f.s.f|
00001410  10 73 89 66 00 00 00 00  00 00 00 00 00 00 00 00  |.s.f............|
00001420  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|

inode 2

根目录

00001480  ed 41 00 00 00 04 00 00  10 73 89 66 13 73 89 66  |.A.......s.f.s.f|
00001490  13 73 89 66 00 00 00 00  00 00 03 00 02 00 00 00  |.s.f............|
000014a0  00 00 00 00 05 00 00 00  07 00 00 00 00 00 00 00  |................|
........  00 00

i_block[15];定义了15个块指针,其中第0-11个是直接块指针,第12个是单间接块指针,第13个是双重间接块指针,第14个是三间接块指针
从addr+0x28 -> addr+0x54都是直接块,这里,根目录有一个直接块指向07(dir entry)

inode 11

lost+found

00001900  c0 41 00 00 00 30 00 00  10 73 89 66 10 73 89 66  |.A...0...s.f.s.f|
00001910  10 73 89 66 00 00 00 00  00 00 02 00 18 00 00 00  |.s.f............|
00001920  00 00 00 00 00 00 00 00  08 00 00 00 09 00 00 00  |................|
00001930  0a 00 00 00 0b 00 00 00  0c 00 00 00 0d 00 00 00  |................|
00001940  0e 00 00 00 0f 00 00 00  10 00 00 00 11 00 00 00  |................|
00001950  12 00 00 00 13 00 00 00  00 00 00 00 00 00 00 00  |................|
00001960  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00001970  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|

lost+found的直接块指向0x08-0x13
所以在第0x2000-0x4c00的位置

inode 12

第一个普通文件,也就是我们file1的inode(之前是全0)

00001980  a4 81 00 00 00 40 00 00  13 73 89 66 13 73 89 66  |.....@...s.f.s.f|
00001990  13 73 89 66 00 00 00 00  00 00 01 00 22 00 00 00  |.s.f........"...|
000019a0  00 00 00 00 01 00 00 00  7f 00 00 00 7d 00 00 00  |............}...|
000019b0  7e 00 00 00 15 00 00 00  16 00 00 00 17 00 00 00  |~...............|
000019c0  18 00 00 00 79 00 00 00  7a 00 00 00 7b 00 00 00  |....y...z...{...|
000019d0  7c 00 00 00 19 00 00 00  1a 00 00 00 00 00 00 00  ||...............|
000019e0  00 00 00 00 b6 00 95 b6  00 00 00 00 00 00 00 00  |................|

直接块指向0x7f 0x7d 0x7e 0x15 0x16 0x17 0x18 0x79 0x7a 0x7b 0x7c 0x19
【0x15-0x19 0x79-0x7f】
还有间接块0x1a

inode table从0x1400开始,但几个文件的inode排列在最后的原因:
前11个inode已经预留了,普通文件的inode从第12个开始

inode没有id之类的序号,查找依靠的就是在inode table里的索引

6 dir entry

存放目录和文件名的块?

00001c00  02 00 00 00 0c 00 01 02  2e 00 00 00 02 00 00 00  |................|
00001c10  0c 00 02 02 2e 2e 00 00  0b 00 00 00 14 00 0a 02  |................|
00001c20  6c 6f 73 74 2b 66 6f 75  6e 64 00 00 0c 00 00 00  |lost+found......|
00001c30  10 00 05 01 66 69 6c 65  31 00 00 00 0d 00 00 00  |....file1.......|
00001c40  10 00 05 01 66 69 6c 65  32 00 00 00 0e 00 00 00  |....file2.......|
00001c50  10 00 05 01 66 69 6c 65  33 00 00 00 0f 00 00 00  |....file3.......|
00001c60  10 00 05 01 66 69 6c 65  34 00 00 00 10 00 00 00  |....file4.......|
00001c70  94 03 05 01 66 69 6c 65  35 00 00 00 00 00 00 00  |....file5.......|
struct ext2_dir_entry_2 {
	__u32	inode;			/* Inode number */
	__u16	rec_len;		/* Directory entry length */
	__u8	name_len;		/* Name length */
	__u8	file_type;
	char	name[EXT2_NAME_LEN];	/* File name */
};

这个块里存放了很多ext2_dir_entry_2条目,他们以4字节对齐,紧凑连接(长度不固定

上述数据分析:

# 第1个是.目录
inode  rec_len  name_len  file_type  name
02     0c       01        02         2e 00 00 00

# 第2个是..目录
inode  rec_len  name_len  file_type  name
02     0c       02        02         2e 2e 00 00

# 第3个是lost+found目录
inode  rec_len  name_len  file_type  name
0b     14       0a        02         6c 6f 73 74 2b 66 6f 75  6e 64 00 00

# 第4个是文件file1
inode  rec_len  name_len  file_type  name
0c     10       05        01         66 69 6c 65  31 00 00 00

7 data区

我也是服了,不同的环境他的这个分布策略也不太一样
之前我在其他环境上测试的结果是连续的,这里就不解释了

00005400  31 31 31 31 31 31 31 31  31 31 31 31 31 31 31 31  |1111111111111111|
...
000067f0  31 31 31 31 31 31 31 31  31 31 31 31 31 31 31 31  |1111111111111111|
00006800  1b 00 00 00 1c 00 00 00  1d 00 00 00 1e 00 00 00  |................|
...
00006c00  31 31 31 31 31 31 31 31  31 31 31 31 31 31 31 31  |1111111111111111|
...
00007bf0  31 31 31 31 31 31 31 31  31 31 31 31 31 31 31 31  |1111111111111111|
00007c00  32 32 32 32 32 32 32 32  32 32 32 32 32 32 32 32  |2222222222222222|
...
000083f0  32 32 32 32 32 32 32 32  32 32 32 32 32 32 32 32  |2222222222222222|
00008400  33 33 33 33 33 33 33 33  33 33 33 33 33 33 33 33  |3333333333333333|
...
00008ff0  33 33 33 33 33 33 33 33  33 33 33 33 33 33 33 33  |3333333333333333|
00009000  25 00 00 00 26 00 00 00  27 00 00 00 28 00 00 00  |%...&...'...(...|
...
00009400  33 33 33 33 33 33 33 33  33 33 33 33 33 33 33 33  |3333333333333333|
...
0000a3f0  33 33 33 33 33 33 33 33  33 33 33 33 33 33 33 33  |3333333333333333|
0000a400  34 34 34 34 34 34 34 34  34 34 34 34 34 34 34 34  |4444444444444444|
...
0000d3f0  34 34 34 34 34 34 34 34  34 34 34 34 34 34 34 34  |4444444444444444|
0000d400  36 00 00 00 37 00 00 00  38 00 00 00 39 00 00 00  |6...7...8...9...|
...
0000d800  34 34 34 34 34 34 34 34  34 34 34 34 34 34 34 34  |4444444444444444|
...
0000e7f0  34 34 34 34 34 34 34 34  34 34 34 34 34 34 34 34  |4444444444444444|
0000e800  35 35 35 35 35 35 35 35  35 35 35 35 35 35 35 35  |5555555555555555|
...
000117f0  35 35 35 35 35 35 35 35  35 35 35 35 35 35 35 35  |5555555555555555|
00011800  47 00 00 00 48 00 00 00  49 00 00 00 4a 00 00 00  |G...H...I...J...|
...
00011c00  35 35 35 35 35 35 35 35  35 35 35 35 35 35 35 35  |5555555555555555|
...
000117f0  35 35 35 35 35 35 35 35  35 35 35 35 35 35 35 35  |5555555555555555|
00011800  47 00 00 00 48 00 00 00  49 00 00 00 4a 00 00 00  |G...H...I...J...|
...
00011c00  35 35 35 35 35 35 35 35  35 35 35 35 35 35 35 35  |5555555555555555|
...
00012bf0  35 35 35 35 35 35 35 35  35 35 35 35 35 35 35 35  |5555555555555555|

00012c00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
...
000183f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00018400  32 32 32 32 32 32 32 32  32 32 32 32 32 32 32 32  |2222222222222222|
...
00018bf0  32 32 32 32 32 32 32 32  32 32 32 32 32 32 32 32  |2222222222222222|
00018c00  64 00 00 00 65 00 00 00  66 00 00 00 67 00 00 00  |d...e...f...g...|
...
00019000  32 32 32 32 32 32 32 32  32 32 32 32 32 32 32 32  |2222222222222222|
...
00019ff0  32 32 32 32 32 32 32 32  32 32 32 32 32 32 32 32  |2222222222222222|
0001a000  33 33 33 33 33 33 33 33  33 33 33 33 33 33 33 33  |3333333333333333|
...
0001c3f0  33 33 33 33 33 33 33 33  33 33 33 33 33 33 33 33  |3333333333333333|
0001c400  32 32 32 32 32 32 32 32  32 32 32 32 32 32 32 32  |2222222222222222|
...
0001e3f0  32 32 32 32 32 32 32 32  32 32 32 32 32 32 32 32  |2222222222222222|
0001e400  31 31 31 31 31 31 31 31  31 31 31 31 31 31 31 31  |1111111111111111|
...
0001fff0  31 31 31 31 31 31 31 31  31 31 31 31 31 31 31 31  |1111111111111111|

8 间接块

需要结合前面的inode和data区中一些奇怪的数据来看
inode table部分我们已经说过,file有一个指向0x1a的单间接块
然后0x1a块的内容:

00006800  1b 00 00 00 1c 00 00 00  1d 00 00 00 1e 00 00 00  |................|

这就是单间接块,块里面充斥着32位无符号数,这里的每个数都表示着一个直接指向的块
0x1b -> 0x1e 【0x6c00 - 0x7800 + 0x400 -1】因为0x7800是最后一个块的起始地址,还要再加上块的大小

对照#7的这段数据,果然符合

00006c00  31 31 31 31 31 31 31 31  31 31 31 31 31 31 31 31  |1111111111111111|
...
00007bf0  31 31 31 31 31 31 31 31  31 31 31 31 31 31 31 31  |1111111111111111|
00007c00  32 32 32 32 32 32 32 32  32 32 32 32 32 32 32 32  |2222222222222222|

双重间接块里放的就是单间接块的地址,以此类推

9 块组

那么,块组在哪里?


其他人写的ext2文件系统博客,总是有一个很经典的图
————————————————————————————————————————————————————
| boot block | Block Group 1 | Block Group 2 | ... |
————————————————————————————————————————————————————

而如果按照我提供的制作脚本制作文件系统镜像,却并没发现第二个块组的踪影,这是为什么呢?

我也是很费解的,linux内核文档有这么一段

Block Groups
------------

Blocks are clustered into block groups in order to reduce fragmentation
and minimise the amount of head seeking when reading a large amount
of consecutive data.  Information about each block group is kept in a
descriptor table stored in the block(s) immediately after the superblock.
Two blocks near the start of each group are reserved for the block usage
bitmap and the inode usage bitmap which show which blocks and inodes
are in use.  Since each bitmap is limited to a single block, this means
that the maximum size of a block group is 8 times the size of a block.

this means that the maximum size of a block group is 8 times the size of a block
如果我没理解错的话,一个块组最多有8个块

那我这个划了128个块的小文件系统镜像应该有十几个块组啊?

好吧,实际上他不是这么实现的

在super block那一节,有这么一个属性:
s_blocks_per_group = 0x2000; 【每个块组拥有8192个块】

我的理解是,至少要划分超过8k个块才会出现第二个块组

但是,以每个块1024的大小计算,8k个块划出的镜像大小超过8MB,这个数据量显然不是我可以手工分析的

所以,就这样

  • 9
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值