ext4文件系統文件定位流程



Ext4文件系統解析

                                 --cache.img爲例,基於32位的文件系統

目錄

Cache文件結構:...2

Cache文件系統結構...2

總體結構...2

超級塊:3

塊組描述符表:4

Inode talble:6

Extern...7

Directory Entries.9

反查inode table尋找文件具體位置...10

總結:...14

 


Cache文件結構:

可見ext4文件系統cache中包含.  ..   hello lost+found hello_world.ko , 其中有四個Directory Entries

和一個Regular file

 

 

Cache文件系統結構

總體結構

Group 0 Padding

ext4 Super Block

Group Descriptors

Reserved GDT Blocks

Data Block Bitmap

inode Bitmap

inode Table

Data Blocks

1024 bytes

1 block

many blocks

many blocks

1 block

1 block

many blocks

many more blocks

 

 

超級塊:

 

Offset

Size

Name

Description

0x0

__le32

s_inodes_count

Total inode count.   0x2000=8192

0x4

__le32

s_blocks_count_lo

Total block count.   0x8000=32768

0x8

__le32

s_r_blocks_count_lo

This number of blocks can only be allocated by the super-user.

0xC

__le32

s_free_blocks_count_lo

Free block count.   0x79f0=31216

0x10

__le32

s_free_inodes_count

Free inode count.   0x1ff2=8178

0x14

__le32

s_first_data_block

First data block. This must be at least 1 for 1k-block filesystems and is typically 0 for all other block sizes.

0x18

__le32

s_log_block_size

Block size is 2 ^ (10 + s_log_block_size).0x2=2^10+2=4096

0x1C

__le32

s_log_cluster_size

Cluster size is (2 ^ s_log_cluster_size) blocks if bigalloc is enabled, zero otherwise.

0x20

__le32

s_blocks_per_group

Blocks per group. 0x8000=32768

0x24

__le32

s_clusters_per_group

Clusters per group, if bigalloc is enabled.

0x28

__le32

s_inodes_per_group

Inodes per group.  0x2000=8192

0x2C

__le32

s_mtime

Mount time, in seconds since the epoch.  0x573bc363

0x30

__le32

s_wtime

Write time, in seconds since the epoch.   0x573bc363

0x34

__le16

s_mnt_count

Number of mounts since the last fsck.     0x06

0x36

__le16

s_max_mnt_count

Number of mounts beyond which a fsck is needed. 0xffff

0x38

__le16

s_magic

Magic signature, 0xEF53      0xEF53 

0x3A

__le16

s_state

File system state. Valid values are:

0x0001

Cleanly umounted

0x0002

Errors detected

0x0004

Orphans being recovered

0x3C

__le16

s_errors

Behaviour when detecting errors. One of:

1

Continue

2

Remount read-only

3

Panic

0x3E

__le16

s_minor_rev_level

Minor revision level. 0x0

0x40

__le32

s_lastcheck

Time of last check, in seconds since the epoch.  0x0

0x44

__le32

s_checkinterval

Maximum time between checks, in seconds. 0x0

0x48

__le32

s_creator_os

OS. One of:

0

Linux

1

Hurd

2

Masix

3

FreeBSD

4

Lites

0x4C

__le32

s_rev_level

Revision level. One of:

0

Original format

1

v2 format w/ dynamic inode sizes

0x50

__le16

s_def_resuid

Default uid for reserved blocks.

0x52

__le16

s_def_resgid

Default gid for reserved blocks.

These fields are for EXT4_DYNAMIC_REV superblocks only.

Note: the difference between the compatible feature set and the incompatible feature set is that if there is a bit set in the incompatible feature set that the kernel doesn't know about, it should refuse to mount the filesystem.

e2fsck's requirements are more strict; if it doesn't know about a feature in either the compatible or incompatible feature set, it must abort and not try to meddle with things it doesn't understand...

0x54

__le32

s_first_ino

First non-reserved inode. 0x0B

0x58

__le16

s_inode_size

Size of inode structure, in bytes. 0x100

0x5A

__le16

s_block_group_nr

Block group # of this superblock. 0x0

 

 

 

塊組描述符表:

 

Offset

Size

Name

Description

0x0

__le32

bg_block_bitmap_lo

Lower 32-bits of location of block bitmap.  0x09

0x4

__le32

bg_inode_bitmap_lo

Lower 32-bits of location of inode bitmap.   0x0a

0x8

__le32

bg_inode_table_lo

Lower 32-bits of location of inode table.       0x0b

0xC

__le16

bg_free_blocks_count_lo

Lower 16-bits of free block count.               0x79f0

0xE

__le16

bg_free_inodes_count_lo

Lower 16-bits of free inode count.                0x1ff2

0x10

__le16

bg_used_dirs_count_lo

Lower 16-bits of directory count.                   0x03

0x12

__le16

bg_flags

Block group flags. Any of:

0x1

inode table and bitmap are not initialized (EXT4_BG_INODE_UNINIT).

0x2

block bitmap is not initialized (EXT4_BG_BLOCK_UNINIT).

0x4

inode table is zeroed (EXT4_BG_INODE_ZEROED).

0x14

__le32

bg_exclude_bitmap_lo

Lower 32-bits of location of snapshot exclusion bitmap.

0x18

__le16

bg_block_bitmap_csum_lo

Lower 16-bits of the block bitmap checksum.

0x1A

__le16

bg_inode_bitmap_csum_lo

Lower 16-bits of the inode bitmap checksum.

0x1C

__le16

bg_itable_unused_lo

Lower 16-bits of unused inode count. If set, we needn't scan past the(sb.s_inodes_per_group - gdt.bg_itable_unused)th entry in the inode table for this group.

0x1E

__le16

bg_checksum

Group descriptor checksum; crc16(sb_uuid+group+desc) if the RO_COMPAT_GDT_CSUM feature is set, or crc32c(sb_uuid+group_desc) & 0xFFFF if the RO_COMPAT_METADATA_CSUM feature is set.

These fields only exist if the 64bit feature is enabled and s_desc_size > 32.

0x20

__le32

bg_block_bitmap_hi

Upper 32-bits of location of block bitmap.

0x24

__le32

bg_inode_bitmap_hi

Upper 32-bits of location of inodes bitmap.

0x28

__le32

bg_inode_table_hi

Upper 32-bits of location of inodes table.

0x2C

__le16

bg_free_blocks_count_hi

Upper 16-bits of free block count.

0x2E

__le16

bg_free_inodes_count_hi

Upper 16-bits of free inode count.

0x30

__le16

bg_used_dirs_count_hi

Upper 16-bits of directory count.

0x32

__le16

bg_itable_unused_hi

Upper 16-bits of unused inode count.

0x34

__le32

bg_exclude_bitmap_hi

Upper 32-bits of location of snapshot exclusion bitmap.

0x38

__le16

bg_block_bitmap_csum_hi

Upper 16-bits of the block bitmap checksum.

0x3A

__le16

bg_inode_bitmap_csum_hi

Upper 16-bits of the inode bitmap checksum.

0x3C

__u32

bg_reserved

Padding to 64 bytes.

 

 

Inode talble:

根據塊組描述符中的bg_inode_table_lo關鍵字可以獲取到inodetable的位置

首先查看 .目錄的table表:bg_inode_table_lo*block_size+2-1*inode_size..目錄的inode_number=2

 

 

位置

名稱

描述

0x0

__le16:0x41ed

i_mode

文件模式

0x2

__le16:0x0000

i_uid

所有者UID.

0x4

__le32:0x00001000

i_size_lo

文件大小.

0x8

__le32:0x00000000

i_atime

讀取時間.

0xC

__le32:0x57395adc

i_ctime

Inode修改時間

0x10

__le32:0x57395adc

i_mtime

文件修改時間.

0x14

__le32:0x00000000

i_dtime

刪除時間

0x18

__le16:0x0000

i_gid

GID.

0x1A

__le16:0x0004

i_links_count

硬鏈接計數.

0x1C

__le32:0x00000008

i_blocks_lo

塊計數(512字節)

0x20

__le32:0x00080080

i_flags

文件標識(ext4使用extent需要標記0x80000)

...

0x28

__le32

i_block[EXT4_N_BLOCKS=15]

塊映射(ext2/3)或區段樹(ext4)

...

 

Extern

由於extern樹使能,因此需要查看extern樹結構體:

40-9960個字節過去是用作塊映射的,如今用作存儲extent信息。extent結構體有12字節的大小,反應快的同學馬上會說,那麼一個inode可以存放最多5extent。然而這是不對的,因爲前12個字節(40-51)被段頭(extentheader)所佔據,所以,一個inode中的區段數最多隻能是4

 

 

首先看段頭:

 

偏移

大小

名稱

描述

0x0

__le16:0xf30a

eh_magic

幻數magic number, 0xF30A.    

0x2

__le16:0x01

eh_entries

區段數.

0x4

__le16:0x03

eh_max

最大的區段數.

0x6

__le16:0x0000

eh_depth

段節點在段樹中的深度。0則表示爲葉子節點,指向數據塊;否則指向其它段節點。

0x8

__le32

eh_generation

暫不討論

 

 

內部節點:

偏移

大小

名稱

描述

0x0

__le32

ei_block

邏輯塊號.

0x4

__le32

ei_leaf_lo

區段樹中下一層的區段節點塊地址(低32位),可以指向葉子節點或者內部節點。

0x8

__le16

ei_leaf_hi

上一欄的高16位地址

0xA

__u16

ei_unused

未使用

 

 

葉子節點:

 

偏移

大小

名稱

描述

0x0

__le320x00000000

ee_block

此區段的第一個塊號,起始塊號

0x4

__le160x0001

ee_len

區段內包含的塊數.

0x6

__le16:0x0000

ee_start_hi

此區段所指向的塊號(高16位)

0x8

__le32:0x0000060c

ee_start_lo

此區段所指向的塊號(低32

 

 

Directory Entries

根據extern tree葉節點所指向的塊號:0x60c*0x1000=0x60c000

Directory Entries結構體

.

Offset

Size

Name

Description

0x0

__le32:0x00000002

inode

Number of the inode

0x4

__le16:0x000C

rec_len

Length of this directory entry.

0x6

__u8:0x01

name_len

Length of the file name.

0x7

__u8:0x02

file_type

File type code, one of:

0x0

Unknown.

0x1

Regular file.

0x2

Directory.

0x3

Character device file.

0x4

Block device file.

0x5

FIFO.

0x6

Socket.

0x7

Symbolic link.

0x8

Char:0x2E=.

name[EXT4_NAME_LEN]

File name.

 

 

 

lost+found:

Offset

Size

Name

Description

0x0

__le32:0x0000000B

inode

Number of the inode

0x4

__le16:0x0014

rec_len

Length of this directory entry.

0x6

__u8:0x0a

name_len

Length of the file name.

0x7

__u8:0x02

file_type

File type code, one of:

0x0

Unknown.

0x1

Regular file.

0x2

Directory.

0x3

Character device file.

0x4

Block device file.

0x5

FIFO.

0x6

Socket.

0x7

Symbolic link.

0x8

Char:lost+found

name[EXT4_NAME_LEN]

File name.

 

 

hello_world.ko

 

Offset

Size

Name

Description

0x0

__le32:0x0000000C

inode

Number of the inode

0x4

__le16:0x0018

rec_len

Length of this directory entry.

0x6

__u8:0x0e

name_len

Length of the file name.

0x7

__u8:0x01

file_type

File type code, one of:

0x0

Unknown.

0x1

Regular file.

0x2

Directory.

0x3

Character device file.

0x4

Block device file.

0x5

FIFO.

0x6

Socket.

0x7

Symbolic link.

0x8

Char:hello_world.ko

name[EXT4_NAME_LEN]

File name.

 

 

 

反查inode table尋找文件具體位置

 

根據hello_world.koinode的節點號,再去inode table中反查,0xB000+(0xC-1)*0x100

 

inode table:

 

位置

名稱

描述

0x0

__le16:0x81ff

i_mode

文件模式

0x2

__le16:0x0000

i_uid

所有者UID.

0x4

__le32:0x00000a80=

2688

i_size_lo

文件大小.

 

0x8

__le32:0x572c42ae

i_atime

讀取時間.

0xC

__le32:0x572c42c2

i_ctime

Inode修改時間

0x10

__le32:0x572c42ae

i_mtime

文件修改時間.

0x14

__le32:0x00000000

i_dtime

刪除時間

0x18

__le16:0x0000

i_gid

GID.

0x1A

__le16:0x0001

i_links_count

硬鏈接計數.

0x1C

__le32:0x00000008

i_blocks_lo

塊計數(512字節)

0x20

__le32:0x00080080

i_flags

文件標識(ext4使用extent需要標記0x80000)

...

0x28

__le32

i_block[EXT4_N_BLOCKS=15]

塊映射(ext2/3)或區段樹(ext4)

...

 

同樣extern樹使能了,所以需要查看extern

 

首先看段頭:

 

偏移

大小

名稱

描述

0x0

__le16:0xf30a

eh_magic

幻數magic number, 0xF30A.    

0x2

__le16:0x01

eh_entries

區段數.

0x4

__le16:0x04

eh_max

最大的區段數.

0x6

__le16:0x0000

eh_depth

段節點在段樹中的深度。0則表示爲葉子節點,指向數據塊;否則指向其它段節點。

0x8

__le32

eh_generation

暫不討論

 

 

內部節點:

偏移

大小

名稱

描述

0x0

__le32

ei_block

邏輯塊號.

0x4

__le32

ei_leaf_lo

區段樹中下一層的區段節點塊地址(低32位),可以指向葉子節點或者內部節點。

0x8

__le16

ei_leaf_hi

上一欄的高16位地址

0xA

__u16

ei_unused

未使用

 

 

葉子節點:

 

偏移

大小

名稱

描述

0x0

__le320x00000000

ee_block

此區段的第一個塊號,起始塊號

0x4

__le160x0001

ee_len

區段內包含的塊數.

0x6

__le16:0x0000

ee_start_hi

此區段所指向的塊號(高16位)

0x8

__le32:0x0000060E

ee_start_lo

此區段所指向的塊號(低32

 

根據extern tree葉節點所指向的塊號:0x60E*0x1000=0x60E000開始的block,數量爲1block

至此一個文件就找到了,就可以根據分區信息計算出位於emmcblock的偏移和數量,然後將文件讀出即可

 

總結:

綜上,其實我們再執行某個分區掛載的時候mount,其實就是將系統的super_block,block_group_des和當前目錄的inode表讀取出來去初始化分配好的結構體。當你讀或者寫一個文件的時候再去更新這些結構體,同時根據結構體的信息去找到你要讀或者寫的文件位於存儲外設的硬件的block的位置,並更新文件內容

 

 


幾個重要的結構體關係圖:


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章