深入理解ext4

来源:互联网 发布:怎么买域名和空间 编辑:程序博客网 时间:2024/05/15 23:46

 文件系统是操作系统的一个重要组成部分,也有着举足轻重的地位。本系列文章主要讲述了linux ext4文件系统的一些实现原理。笔者参考了2.6.32.60的内核源代码。在写这篇的文章时,最新的内核已经去到了3.7.9。

ext4是替代ext2/3Linux文件系统。从2.6.28版本开始,被正式认定进入稳定(stable)。本文主要介绍ext4文件系统在硬盘层面上的存储结构及原理。

 

读者对象:对Linux有一定基础,希望了解ext4底层原理,和它与ext2/3系统区别。

 

关键词汇

先回顾几个基本的概念,如果不是特别清楚下面几个概念的话,可以去google一下。

inode:索引节点

superblock:超级块

block:文件系统块

block group:文件系统块组

disk block:磁盘块(512字节)

block device:块设备

VFS:虚拟文件系统

EXT4存储结构

假如把整个超级块比如一本书,那么文件系统的工作就是把要记录的内容,按页码,行段记录在这本书里。这当然也包括书的目录了。我们使用dumpe2fs工具输出:

 

Reserved GDT blocks:      609

Blocks per group:         32768

Fragments per group:      32768

Inodes per group:         8128

Inode blocks per group:   508

Flex block group size:    16

Filesystem created:       Mon May 14 13:30:51 2012

Last mount time:          Sun Jan  6 18:51:16 2013

Last write time:          Sun Jan  6 18:51:16 2013

Mount count:              282

Maximum mount count:      -1

Last checked:             Mon May 14 13:30:51 2012

Check interval:           0 (<none>)

Lifetime writes:          20 GB

Reserved blocks uid:      0 (user root)

Reserved blocks gid:      0 (group root)

First inode:              11

Inode size:               256

Required extra isize:     28

Desired extra isize:      28

Journal inode:            8

 

首先,映入眼帘的是该超级块的相关重要参数,比如inode大小,块组含块数,块组inode数目等等。这些数据是存在ext4_super_blockext4_sb_info这两个结构体中,定义在ext4.h头文件里,它们不是本篇重要讨论的内容。我们只需要知道它们是存放一些超级块信息的结构体即可。

接下来,可以看到ext4硬盘上的存储结构:

Group 0: (Blocks 0-32767) [ITABLE_ZEROED]

  Checksum 0x7cf3, unused inodes 0

  Primary superblock at 0, Group descriptors at 1-2

  Reserved GDT blocks at 3-611

  Block bitmap at 612 (+612), Inode bitmap at 628 (+628)

  Inode table at 644-1151 (+644)

  2720 free blocks, 0 free inodes, 1383 directories

  Free blocks: 8888-8959, 9068, 9071-9135, 9144-9175, 9200-9207, 9213-9214, 9279, 9700-10120, 11823-11964, 12213-12870, 12879-13043, 13139-13254, 18432-19021, 22748-22975, 32549-32767

  Free inodes:

 

这是块组0的情况,它表明块组0由块号为0-3276732768个块组成,超级块基本信息存在块0,块组描述符在块1-2,预留的块组描述符表在块3-611,块位图在块612中,inode位图在块628中,Inode表在块644-1151中,空闲的块有很多,空闲的inode没了。

接下来,我们将重点分析这句废话中每个词的含义

        超级块基本信息:

                  我们在前面已经讲过了。顾名思义,不多解释。

         块组描述符

                  在内核中就是结构体ext4_group_desc,它包括的内容为:块位图块号,inode位图块号,inode表块号,空闲块计数,自由块计数等等。

         预留的块组描述符表

                  为以后要使用所留下来的空间。

         块位图

                  这个就是一个块使用情况记录表。记录哪些块使用,哪些块未使用。它的原理就是对整个块组中0-32767这总共32768个块中作一个映射。根据一个bytes8个位00000000,一个块有4096bytes也就是有4096*8=32768个位,这32768个位刚好对应了块组中32768的块。如果第N个块被使用了则标记第N位为1,否则为0

         inode位图

                  和上面的块位图一样,这个是inode的使用情况记录表。由超级块基本信息可以看到每个块组有8128inode,这里对inode的映射原理和块位图也是一样,只不过         没有用满一个块。

         inode

                  inode表就是具体存放inode信息的地方。在ext4中,inode的大小为256字节(ext2/3中仅有它的一半,128字节),一个块可以存放16inode,由于一个块组有8128          inode,总共需要8128/16=508个块存放inode表。这个值可以在超级块基本信息中的Inode blocks per group中看到。

讲完了这些词的含义,我们对group 0有了初步的了解。那么group 1呢?

Group 1: (Blocks 32768-65535) [ITABLE_ZEROED]

  Checksum 0xbb99, unused inodes 0

  Backup superblock at 32768, Group descriptors at 32769-32770

  Reserved GDT blocks at 32771-33379

  Block bitmap at 613 (+4294935141), Inode bitmap at 629 (+4294935157)

  Inode table at 1152-1659 (+4294935680)

  598 free blocks, 0 free inodes, 648 directories

  Free blocks: 33424-33439, 33442-33443, 33564-33627, 33644-33647, 33652-33663, 33725-33871, 33878-33931, 33934-33973, 33976-33983, 34046-34047, 34176-34303, 36008, 36015, 36019, 36412, 40299-40415

  Free inodes:

 

我们看到group 1 中,primary superblock 变为了backup superblock,由于超级块基本信息对于文件系统至关重要,为了系统的健壮性,ext文件系统在每个块组中都进行了备份。ext4考虑到在每个块组中都备份有点多余,尤其是组描述符表所以就仅在块号以357为幂的块组上进行备份。

用个表格表示超级块中块组的结构:

ext4 超级块

块组描述符

Reserved GDT Blocks

数据块位图

Inode位图

inode 表

数据块

1 block

若干blocks

若干 blocks

1 block

1 block

若干

好多好多块

                                                                                                                                                    

inode

Purpose

0

Doesn't exist; there is no inode 0.

1

List of defective blocks.

2

Root directory.

3

ACL index.

4

ACL data.

5

Boot loader.

6

Undelete directory.

7

Reserved group descriptors inode.

8

Journal inode.

11

First non-reserved inode. Usually this is the lost+found directory.

 

块寻址

ext4的块寻址已经改为48位。这种设计改动是为了支持更大的文件系统大小。EXT4使用了区段(extents)这个概念,取代了过去早期UNIX文件系统中(ext2/3)中低效的非直接块映射机制。区段和NTFS上的cluster有点类似,它们都是选定了一个特定的块地址并把数个块组合一个区间。一个文件如果是碎片化的,那么就意味它着拥有多个区段, ext4会尽它自己的努力保持文件连续。

 

这种新的块寻址策略导致了先前工具的大部分问题。举个列子:

 

[root@localhost Desktop]# stat math.c

  File: `math.c'

  Size: 1477               Blocks: 8          IO Block: 4096   regular file

Device: fd00h/64768d     Inode:420402      Links: 1

Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)

Access: 2013-01-05 15:07:11.815541582 +0800

Modify: 2012-08-20 13:40:02.496797954 +0800

Change: 2012-12-30 11:28:54.751357610 +0800

 

 

由上面得到文件math.cInode号为420402

[root@localhost Desktop]# istat /dev/mapper/VolGroup-lv_root 420402

inode: 420402

Allocated

Group: 51

Generation Id: 1062005310

uid / gid: 0 / 0

mode: rrw-r--r--

Flags:

size: 1477

num of links: 1

 

Inode Times:

Accessed:         2013-01-05 15:07:11 (CST)

File Modified:   2012-08-20 13:40:02 (CST)

Inode Modified:        2012-12-30 11:28:54 (CST)

 

Direct Blocks:

127754

 

 

由上面的命令结果可以看到,Inode位于节点上块组51上,留意上面命令最下面有Direct Blocks这一行,这一行写着127754。在ext4的文件系统中,由于direct block映射的块寻址机制被取代,而采取的是extent区段树的块寻址。这个地方的值基本上是无效的。127754这个值十六进制表示为0x1f30a,我们在稍后的讨论这个值的来源。

我们知道了math.c这个文件的inode号码为420402,那么怎样知道它数据块是拿一个呢?

由前面的内容我们知道,每个块可以存16inode,那么420402则在第420402/16=26275.125个块中,也就是位于第26275个块的第二个位置。每个块组有508inode块,那么26725/508=51.72可以得知,位于块组51号之中,这个值可以在我们之前istat中可以验证。

那么具体是51块组中的哪个块呢?我们先确定这个inode块是在块组中的第几个块。因为每个块组有508inode块,51块组前面共有51*508=25908个块。第26275inode块在51块组中排在26275-25908=367的位置。查看51块组的描述:

 

Group 51: (Blocks 1671168-1703935) [ITABLE_ZEROED]

  Checksum 0x5ffd, unused inodes 0

  Block bitmap at 1572867 (+4294868995), Inode bitmap at 1572883 (+4294869011)

  Inode table at 1574420-1574927 (+4294870548)

  34 free blocks, 1 free inodes, 541 directories

  Free blocks: 1672899, 1673339, 1673344, 1674035, 1674054, 1674062, 1674077, 16

74334, 1674353-1674354, 1674423, 1675259, 1675754-1675755, 1675763, 1675860-1675

861, 1675867, 1675979, 1676183, 1676287, 1676367, 1676507, 1676526-1676527, 1676

567, 1676711, 1676743, 1676924-1676925, 1676934, 1691649, 1691658, 1691707

  Free inodes: 422608

 

看到inode的起点位于1574420,由此,我们想要找的inode信息的块就存在于1574787inode块中的第二个。

可以使用blkcat查看1574787的内容,我们用vi切换到16进制模式打开如下:

 

0000070: 0000 0000 0000 0000 0000 0000 0000 0000  ................

0000080: 1c00 0000 4430 c1a7 c8f1 733d fc8a 6cb1  ....D0....s=..l.

0000090: 58a8 b04f 04a0 6538 0000 0000 0000 02ea  X..O..e8........

00000a0: 0706 3c00 0000 0000 2200 0000 0000 0000  ..<.....".......

00000b0: 7365 6c69 6e75 7800 0000 0000 0000 0000  selinux.........

00000c0: 0000 0000 0000 0000 0000 0000 0000 0000  ................

00000d0: 0000 0000 0000 0000 0000 0000 7379 7374  ............syst

00000e0: 656d 5f75 3a6f 626a 6563 745f 723a 6164  em_u:object_r:ad

00000f0: 6d69 6e5f 686f 6d65 5f74 3a73 3000 0000  min_home_t:s0...

0000100: a481 0000 c505 0000 1fd1 e750 f6b4 df50  ...........P...P

0000110: b2cd 3150 0000 0000 0000 0100 0800 0000  ..1P............

0000120: 0000 0800 0100 0000 0af3 0100 0400 0000  ................

0000130: 0000 0000 0000 0000 0100 0000 d64a 1c00  .............J..

0000140: 0000 0000 0000 0000 0000 0000 0000 0000  ................

 

 我们知道inodesize大小为256字节,那么第二个inode的起始位置也就是256=0x100处。

这个时候,我们看下inode的数据结构:

 

位置

名称

描述

0x0

__le16

i_mode

文件模式

0x2

__le16

i_uid

所有者UID.

0x4

__le32

i_size_lo

文件大小.

0x8

__le32

i_atime

读取时间.

0xC

__le32

i_ctime

Inode修改时间

0x10

__le32

i_mtime

文件修改时间.

0x14

__le32

i_dtime

删除时间

0x18

__le16

i_gid

GID.

0x1A

__le16

i_links_count

硬链接计数.

0x1C

__le32

i_blocks_lo

块计数(512字节)

0x20

__le32

i_flags

文件标识(ext4使用extent需要标记0x80000)

...

0x28

__le32

i_block[EXT4_N_BLOCKS=15]

块映射(ext2/3)或区段树(ext4)

...

 

我们按照表中的结构,对照上面的块码:

 

偏移

大小

名称

描述

0x0

0x81a4

i_mode

文件模式

0x2

0x0000

i_uid

所有者UID.

0x4

0x0000 05c5

i_size_lo

文件大小.

0x8

0x50e7 d11f

i_atime

读取时间.

0xC

0x50df b4f6

i_ctime

Inode修改时间

0x10

0x5031 b2cd

i_mtime

文件修改时间.

0x14

0x0000 0000

i_dtime

删除时间

0x18

0x0000

i_gid

GID.

0x1A

0x0001

i_links_count

硬链接计数.

0x1C

0x0000 0008

i_blocks_lo

块计数(512字节)

0x20

0x0080 0000

i_flags

文件标识(ext4使用extent需要标记0x80000)

...

0x28

 ...

i_block[EXT4_N_BLOCKS=15]

块映射(ext2/3)或区段树(ext4)

...

 

细心的同学会发现大小的顺序是倒过来的,这是因为__lexx类型,lelittle endian小端开始的缩写,意思就是从小到大的顺序。我们看到文件的大小为0x5c5=1477,这说明我们找的正是math.cinode

 

因为ext4 使用区段去代替了块映射去查找文件的内容。从40-9960个字节过去是用作块映射的,如今用作存储extent信息。extent结构体有12字节的大小,反应快的同学马上会说,那么一个inode可以存放最多5extent。然而这是不对的,因为前12个字节(40-51)被段头(extent header)所占据,所以,一个inode中的区段数最多只能是4

 

现在,我们重点开始讲区段树(extent tree)

ext4中,区段树取代了旧式的逻辑块映射。这是因为在老的模式中,分配连续的1000个块需要映射这1000个块的地址。但使用了区段,只需要映射一个区段并把区段的长度标记为1000ee_len=1000)。如果起用了flex_bg的功能,一个区段可以分配一个很大的文件,这降低了元数据的大小,也提高了硬盘的效率。inode必须使用区段标记0x80000开启区段的功能。

区段的结构是树形的。每个树节点的起始为:struct ext4_extent_header(这是一个结构体,我们接下来会给大家描述它的内容)。如果一个节点是树的内部节点(即eh.eh_depth>0),那么eh.eh_entries的指针将指向struct ext4_extent_idx;每个这些索引都指向一个块,块中包含更多的区段树中的节点。如果节点是树的叶子节点(eh.eh_depth=0),那么eh.eh_entries的指针将指向struct ext4_extent;这些结构体中指向文件的数据块。区段树的根节点存在inode.i_block,也就是我们在前面讨论的从40-99的那60个字节里。

 

说了这么多,我们还是赶紧看看extent的结构吧;

 

首先出场的是段头(extent header)

 

偏移

大小

名称

描述

0x0

__le16

eh_magic

幻数magic number, 0xF30A.

0x2

__le16

eh_entries

区段数.

0x4

__le16

eh_max

最大的区段数.

0x6

__le16

eh_depth

段节点在段树中的深度。0则表示为叶子节点,指向数据块;否则指向其它段节点。

0x8

__le32

eh_generation

暂不讨论

 

同样的,对照我们的实际数据看看

 

偏移

大小

名称

描述

0x0

0xf30a

eh_magic

幻数magic number, 0xF30A.

0x2

0x0001

eh_entries

区段数.

0x4

0x0004

eh_max

最大的区段数.

0x6

0x0000

eh_depth

段节点在段树中的深度。0则表示为叶子节点,指向数据块;否则指向其它段节点。

0x8

0x0000 0000

eh_generation

暂不讨论

 

 

接下来我们先看struct ext4_extent_idx,这个结构在前面我们有提到过,用于extent树的内部节点。

 

偏移

大小

名称

描述

0x0

__le32

ei_block

逻辑块号.

0x4

__le32

ei_leaf_lo

区段树中下一层的区段节点块地址(低32位),可以指向叶子节点或者内部节点。

0x8

__le16

ei_leaf_hi

上一栏的高16位地址

0xA

__u16

ei_unused

未使用

 

我们接着看struct ext4_extent,叶子节点的结构体

 

偏移

大小

名称

描述

0x0

__le32

ee_block

此区段的第一个块号,起始块号

0x4

__le16

ee_len

区段内包含的块数.

0x6

__le16

ee_start_hi

此区段所指向的块号(高16位)

0x8

__le32

ee_start_lo

此区段所指向的块号(低32位)

 

对照我们的实际数据看看

 

偏移

大小

名称

描述

0x0

0x0000 0000

ee_block

此区段的第一个块号,起始块号

0x4

0x0001

ee_len

区段内包含的块数.

0x6

0x0000

ee_start_hi

此区段所指向的块号(高16位)

0x8

0x001c 4ad6

ee_start_lo

此区段所指向的块号(低32位)

 

由上表可以看到,因为我们的文件较小,这里作为叶子节点直接指向了文件数据块。数据块号为0x001c4ad6=1854166。我们使用命令查看块中的内容:

[root@localhost Desktop]# blkcat /dev/mapper/VolGroup-lv_root 1854166

#include <stdlib.h>

#include <math.h>

...

 

呵呵,可以看到,这就是我们的math.c文件。

 

思考:

请读者找一个大于4k的文件,看看能不能找到它的数据块。

 

删除文件

执行rm后删除文件,数据块并没有被清除,inode被释放,有下面3项会改变: 1. 文件大小被置为0

    2. 段头中的区段值被设为0

    3. 区段被清空

清空了区段意味着我们会失去文件起始物理块的地址和区段的长度。也就是说,在inode中已经不存在元数据可以帮我们恢复文件。这种行为和ext3回收inode时清除inode中的块指针很相似。这样就意味着我们只能靠传统的file-carving去恢复文件。

还记得在上一章中,我们提到过的结构体struct ext4_extent_idx。这个结构体表示在extent tree中的节点。 我们在前面的章节已经阐述过,ext4使用extent取代了传统的block映射方式。我们的案例中只展示了只有一个extent的情况。本篇文章将介绍多个extent情况下的具体细节。

 

在本文中,我们选取了文件/var/log/messages,它是系统日志的记录文件,由于它的角色特殊,时间长了会造成给很多的碎片。我们还是先看看他的inode,方法和(一)中描述的一致,在此不重复了。

 

 

0000c00: 8081 0000 d036 0000 814b ee50 7f4b ee50  .....6...K.P.K.P

0000c10: 7f4b ee50 0000 0000 0000 0100 2000 0000  .K.P........ ...

0000c20: 0000 0800 0100 00000af30400 0400 0000  ................

0000c30: 0000 0000 0000 0000 0100 0000 58c2 0b00  ............X...

0000c40: 0100 0000 0100 0000 e599 1b00 0200 0000  ................

0000c50: 0100 0000 41e6 2f00 0300 0000 0100 0000  ....A./.........

0000c60: b878 1c00 275f ea72 0000 0000 0000 0000  .x..'_.r........

0000c70: 0000 0000 0000 0000 0000 0000 0000 0000  ................

0000c80: 1c00 0000 c018 94d1 c018 94d1 c0e5 ea86  ................

0000c90: 9bea e850 d0a4 fcb4 0000 0000 0000 02ea  ...P............

0000ca0: 0706 4000 0000 0000 1f00 0000 0000 0000  ..@.............

0000cb0: 7365 6c69 6e75 7800 0000 0000 0000 0000  selinux.........

0000cc0: 0000 0000 0000 0000 0000 0000 0000 0000  ................

0000cd0: 0000 0000 0000 0000 0000 0000 0000 0000  ................

0000ce0: 7379 7374 656d 5f75 3a6f 626a 6563 745f  system_u:object_

0000cf0: 723a 7661 725f 6c6f 675f 743a 7330 0000  r:var_log_t:s0..

 

 

0x0af3开始,这是extent header起始的标记,我们还是像(一)那样,对照着表看

 

偏移

大小

名称

描述

0x0

0xf30a

eh_magic

幻数magic number, 0xF30A.

0x2

0x0004

eh_entries

区段数.

0x4

0x0004

eh_max

最大的区段数.

0x6

0x0000

eh_depth

段节点在段数中的深度。0则表示为叶子节点,指向数据块;否则指向其它段节点。

0x8

0x0000

eh_generation

暂不讨论

 

因为这里看到depth0,说明extent中指向的是数据块。在extent header中接下来的将extent是我们把接下来的数据对应到它的表中

 

偏移

大小

名称

描述

0x0

0x0000 0000

ee_block

此区段的第一个块号,起始块号

0x4

0x0001

ee_len

区段内包含的块数.

0x6

0x0000

ee_start_hi

此区段所指向的块号(高16位)

0x8

0x000b c258

ee_start_lo

此区段所指向的块号(低32位)

 

接下来的12个字节

 

偏移

大小

名称

描述

0x0

0x0000 0001

ee_block

此区段的第一个块号,起始块号

0x4

0x0001

ee_len

区段内包含的块数.

0x6

0x0000

ee_start_hi

此区段所指向的块号(高16位)

0x8

0x001b 99e5

ee_start_lo

此区段所指向的块号(低32位)

 

再接下来的12个字节

 

偏移

大小

名称

描述

0x0

0x0000 0002

ee_block

此区段的第一个块号,起始块号

0x4

0x0001

ee_len

区段内包含的块数.

0x6

0x0000

ee_start_hi

此区段所指向的块号(高16位)

0x8

0x00f2 e641

ee_start_lo

此区段所指向的块号(低32位)

 

最后的12个字节 

偏移

大小

名称

描述

0x0

0x0000 0003

ee_block

此区段的第一个块号,起始块号

0x4

0x0001

ee_len

区段内包含的块数.

0x6

0x0000

ee_start_hi

此区段所指向的块号(高16位)

0x8

0x001c 78b8

ee_start_lo

此区段所指向的块号(低32位)

 

可以通过使用blkcat看到4个块刚好凑成了messages文件,疑心重的同学可以把4个块拼成一个文件,用md5sum比较一下。这里我们并没有想看到extent中的内部节点情况。没关系,我们系统日志文件时会随着时间增长。正在笔者撰写此文时,messages已经变大了,并且超过了16k的大小,也就是超出了4个块。这时候我们看看messagesinode信息,方法不重复了。

 

0000c00: 8081 0000 4f51 0000 eb84 ef50 ea84 ef50  ....OQ.....P...P

0000c10: ea84 ef50 0000 0000 0000 0100 3800 0000  ...P........8...

0000c20: 0000 0800 0100 00000af3 0100 0400 0100  ................

0000c30: 0000 0000 0000 0000 7c03 1c00 0000 0b00  ........|.......

0000c40: 0100 0000 0100 0000 e599 1b00 0200 0000  ................

0000c50: 0100 0000 41e6 2f00 0300 0000 0100 0000  ....A./.........

0000c60: b878 1c00 275f ea72 0000 0000 0000 0000  .x..'_.r........

0000c70: 0000 0000 0000 0000 0000 0000 0000 0000  ................

0000c80: 1c00 0000 c80e c097 c80e c097 accd 3948  ..............9H

0000c90: 9bea e850 d0a4 fcb4 0000 0000 0000 02ea  ...P............

0000ca0: 0706 4000 0000 0000 1f00 0000 0000 0000  ..@.............

0000cb0: 7365 6c69 6e75 7800 0000 0000 0000 0000  selinux.........

0000cc0: 0000 0000 0000 0000 0000 0000 0000 0000  ................

0000cd0: 0000 0000 0000 0000 0000 0000 0000 0000  ................

0000ce0: 7379 7374 656d 5f75 3a6f 626a 6563 745f  system_u:object_

0000cf0: 723a 7661 725f 6c6f 675f 743a 7330 0000  r:var_log_t:s0..

 

 

经过一段时间的练习,同学们应该不需要对照表来识辨这些16进制码的含义了,如果不熟练的话,可以回过头多看几遍。我们看到这个inode较之前有了变化。extent的区段数变成了1,区段树的深度变成了1。区段树深度为1,这说明非叶子节点。

 

偏移

大小

名称

描述

0x0

0x0000 0000

ei_block

逻辑块号.

0x4

0x001c 037c

ei_leaf_lo

区段树中下一层的区段节点块地址(低32位),可以指向叶子节点或者内部节点。

0x8

0x0000

ei_leaf_hi

上一栏的高16位地址

0xA

0x000b

ei_unused

未使用

 

使用blkcat查看文件系统块1835900的内容,

 

0000000: 0af3 0e00 5401 0000 0000 0000 0000 0000  ....T...........

0000010: 0100 0000 58c2 0b00 0100 0000 0100 0000  ....X...........

0000020: e599 1b00 0200 0000 0100 0000 41e6 2f00  ............A./.

0000030: 0300 0000 0100 0000 b878 1c00 0400 0000  .........x......

0000040: 0100 0000 2d8b 1b00 0500 0000 0100 0000  ....-...........

0000050: 9a79 1c00 0600 0000 0100 0000 0d82 1b00  .y..............

0000060: 0700 0000 0100 0000 1182 1b00 0800 0000  ................

0000070: 0100 0000 1382 1b00 0900 0000 0100 0000  ................

0000080: 1682 1b00 0a00 0000 0100 0000 1882 1b00  ................

0000090: 0b00 0000 0300 0000 034e 1c00 0e00 0000  .........N......

00000a0: 0200 0000 074e 1c00 1000 0000 0400 0000  .....N..........

00000b0: e082 0c00 0000 0000 0000 0000 0000 0000  ................

 

 

从上面的数据,我们可以看到有0x000e个区段,也就是在extent header后有14extent或者extent ixd的结构体。接着看到extent最大数为0x0154=340,这个数字是怎么来的呢?我们知道在一个inode里面,这个值是4,那是因为('extent space' - 'extent header size') / 'extent size' (60-12)/12=4,那么在这里也一样,只不过60这里要变为4096,因为我们不在inode中,而是在一个块中,即4096-12=4084,4084/12340.333,最后还剩4个字节浪费了。再接着,是树的深度,也就是0x0000表明是叶子节点。那么我们知道,这个文件由着14block的块组成。有兴趣的同学可以自己把文件dump出来拼一下。呵呵。



原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 考驾照怕过不了怎么办 学车对车没感觉怎么办 居住证到期2个月怎么办 生育险差一个月怎么办 驾照扣了38分怎么办 新疆转入山东上学怎么办手续 驾照过日期换证怎么办 机动车被扣24分怎么办 车辆被扣24分怎么办 现在深圳牌十年老车怎么办? 护士证过期4年了怎么办 护士资格证延续注册过期了怎么办 护士资格证过期没注册怎么办 护士资格证注册时间过期怎么办 辅警体检视力不行怎么办 护士延续注册体检怀孕怎么办 护士资格证没有延续注册怎么办 申请信用卡没有座机号码怎么办 网上申请信用卡没有座机号码怎么办 我叫上门服务被骗了怎么办 上门服务被骗了3000多怎么办 微信被骗9000元怎么办 奥迪a8气囊灯亮怎么办 驾考站岗迟到了怎么办 老板欠员工工资不给怎么办 如果有一天我没头发了怎么办 苏州公积金密码忘了怎么办 科二考试第二把怎么办 科一老是记不住怎么办 科目二考试没去怎么办 网约车驾龄不到怎么办 科四预约不上怎么办 教练不退钱怎么办找谁 驾考出入证丢了怎么办 科二成绩单丢了怎么办 考驾照的准考证丢了怎么办 驾考预约去不了怎么办 科目一预约没去怎么办 打狂犬疫苗期间感冒了怎么办 公司社保欠费不交怎么办 25号社保不交怎么办欠费