源码分析网上太多了,不写了,记录简单的实践步骤:
1. 创建ext2文件镜像并映射
cd /tmp dd if=/dev/zero of=ext2-1M.img bs=1024 count=1024 mkfs.ext2 ext2-1M.img mkdir ext2 sudo mount -o loop ext2-1M.img ext2
2. 在ext2文件系统内创建一个普通文件,方便测试
cd ext2 touch test echo "test content" > test
3. 用vim打开ext2-1M.img,十六进制查看(:%!xxd)
4. 查看block大小,定位各个磁盘数据结构的位置
所以超级快的地址为1 * 1024 = 0x400,可以对照着数据结构ext2_super_block来分析文件内容,通过/sbin/dumpe2fs /dev/loop0来验证分析是否正确。
第一个组描述符在第二个block: 0x800,类似的可以对照着数据结构ext2_group_desc来分析文件内容,通过/sbin/dumpe2fs来验证结果。
找到了组描述符便可以找到数据快位图(bg_block_bitmap)、索引节点位图(bg_inode_bitmap)、索引节点表(bg_inode_table)等结构的位置。
5. 通过文件索引节点标号找到文件内容
查看测试文件的索引节点编号:
每个group里的索引节点个数为ext2_super_block.s_inodes_per_block,在结构体ext2_super_block中的偏移量40,也就是为0x28,因此在文件中的地址为0x428:
0x428处的值为0x00000080,也就是128,因此节点编号12(编号从1开始)所在的group为(12 -1 ) / 128 = 0,也就是第一个group;在inode table中的下标为(12 -1) % 128 = 11。
inode table的地址在ext2_group_desc.bg_inode_table,文件中地址为0x808,值为0x0008,也就是inode table起始于第八个blcok,地址为1024*8=0x2000。
每个inode大小为128字节,因此inode table index为11的inode地址为11 * 128 + 0x2000 = 0x002580:
该地址对应结构体ext2_inode:
struct ext2_inode { __le16 i_mode; /* File mode */ __le16 i_uid; /* Low 16 bits of Owner Uid */ __le32 i_size; /* Size in bytes */ __le32 i_atime; /* Access time */ __le32 i_ctime; /* Creation 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; /* Blocks count */ __le32 i_flags; /* File flags */ union { struct { __le32 l_i_reserved1; } linux1; struct { __le32 h_i_translator; } hurd1; struct { __le32 m_i_reserved1; } masix1; } osd1; /* OS dependent 1 */ __le32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */ __le32 i_generation; /* File version (for NFS) */ __le32 i_file_acl; /* File ACL */ __le32 i_dir_acl; /* Directory ACL */ __le32 i_faddr; /* Fragment address */ union { struct { __u8 l_i_frag; /* Fragment number */ __u8 l_i_fsize; /* Fragment size */ __u16 i_pad1; __le16 l_i_uid_high; /* these 2 fields */ __le16 l_i_gid_high; /* were reserved2[0] */ __u32 l_i_reserved2; } linux2; struct { __u8 h_i_frag; /* Fragment number */ __u8 h_i_fsize; /* Fragment size */ __le16 h_i_mode_high; __le16 h_i_uid_high; __le16 h_i_gid_high; __le32 h_i_author; } hurd2; struct { __u8 m_i_frag; /* Fragment number */ __u8 m_i_fsize; /* Fragment size */ __u16 m_pad1; __u32 m_i_reserved2[2]; } masix2; } osd2; /* OS dependent 2 */ };
i_size为0x0d,i_block偏移量为0x28,文件中地址为0x0025a8,i_block[0]的值为0x0026:
也就是说文件第一个block内容位于第0x26,也就是第38个block,地址为38*1024=0x9800,跳转过去便可以发现文件内容:test content
六:参考
- 《深入理解Linux内核》
- http://bbs.chinaunix.net/thread-2329690-1-1.html
- http://elixir.free-electrons.com/linux/v3.6/source