linux磁盘第一个扇区分析,Linux文件系统分析 | 学步园

这里的分析有别于一般书上讲的Linux文件系统分析,主要区别是:这里的分析与其说是文件系统分析倒不如说是Linux磁盘映象的分析,

首先从获取磁盘映象开始,然后分析磁盘映象的结构,内核文件系统部分的代码无非就是对磁盘映象的管理罢了。

依据读源代码的体会,Linux文件系统实现可以看作三个部分:用户眼中的文件系统,内存中的文件系统,磁盘上的文件系统。用户眼中

的文件系统是指open,read等系统调用的实现以及目录树状结构的实现,内存中的文件系统是指缓冲管理,VFS等开机mount后在内存中出现的

文件系统,而磁盘上的文件系统就是指磁盘映象。这里的分析主要着重在第三部分,即磁盘映象。

首先就是磁盘映象的获取,最简单的方法就是使用dd命令:dd if=/dev/hda of=/home/lw/hda.dd bs=2k。这个命令把hda上的文件系统磁

盘映象全部复制到hda.dd文件中,这个命令执行需要的时间主要取决于hda磁盘的大小,bs参数表示每次读些的单元大小,一般设为2k,8k都

行,效率上会有些细微的区别。接下来就对hda.dd文件进行分析就可以了。由于这个文件一般都很大,二进制阅读工具运行起来会很慢,所以

最好还是建立一个软盘ext2文件系统,然后进行分析。当然还有其他的方法:直接拷贝虚拟机磁盘映象来分析。

下面的分析是使用软盘上建立的文件系统,然后dd倒出来的rootimage文件来分析磁盘映象。让我们先来看看第一个扇区的内容

00000000h: EB 3C 90 4D 53 44 4F 53 35 2E 30 00 02 01 01 00 ; ?怣SDOS5.0.....

00000010h: 02 E0 00 40 0B F0 09 00 12 00 02 00 00 00 00 00 ; .?@.?.........

00000020h: 00 00 00 00 00 00 29 57 23 8D 0E 20 20 20 20 20 ; ......)W#?

00000030h: 20 20 20 20 20 20 46 41 54 31 32 20 20 20 FA 33 ;       FAT12   ?

00000040h: C0 8E D0 BC 00 7C 16 07 BB 78 00 36 C5 37 1E 56 ; 缼屑.|..粁.6?.V

00000050h: 16 53 BF 3E 7C B9 0B 00 FC F3 A4 06 1F C6 45 FE ; .S?|?.?.艵?

00000060h: 0F 8B 0E 18 7C 88 4D F9 89 47 02 C7 07 3E 7C FB ; .?.|圡鶋G.?>|?

00000070h: CD 13 72 79 33 C0 39 06 13 7C 74 08 8B 0E 13 7C ; ?ry3?..|t.?.|

00000080h: 89 0E 20 7C A0 10 7C F7 26 16 7C 03 06 1C 7C 13 ; ? |?|?.|...|.

00000090h: 16 1E 7C 03 06 0E 7C 83 D2 00 A3 50 7C 89 16 52 ; ..|...|円.|?R

000000a0h: 7C A3 49 7C 89 16 4B 7C B8 20 00 F7 26 11 7C 8B ; ||?K|?.?.|?

000000b0h: 1E 0B 7C 03 C3 48 F7 F3 01 06 49 7C 83 16 4B 7C ; ..|.肏黧..I|?K|

000000c0h: 00 BB 00 05 8B 16 52 7C A1 50 7C E8 92 00 72 1D ; .?.?R||钂.r.

000000d0h: B0 01 E8 AC 00 72 16 8B FB B9 0B 00 BE E6 7D F3 ; ?璎.r.孄?.炬}?

000000e0h: A6 75 0A 8D 7F 20 B9 0B 00 F3 A6 74 18 BE 9E 7D ; .? ?.螃t.緸}

000000f0h: E8 5F 00 33 C0 CD 16 5E 1F 8F 04 8F 44 02 CD 19 ; 鑏.3劳.^.?廌.?

00000100h: 58 58 58 EB E8 8B 47 1A 48 48 8A 1E 0D 7C 32 FF ; XXX腓婫.HH?.|2?BR>00000110h: F7 E3 03 06 49 7C 13 16 4B 7C BB 00 07 B9 03 00 ; 縻..I|..K|?.?.

00000120h: 50 52 51 E8 3A 00 72 D8 B0 01 E8 54 00 59 5A 58 ; PRQ?.r匕.鑄.YZX

00000130h: 72 BB 05 01 00 83 D2 00 03 1E 0B 7C E2 E2 8A 2E ; r?..円....|忖?

00000140h: 15 7C 8A 16 24 7C 8B 1E 49 7C A1 4B 7C EA 00 00 ; .|?$|?I||?.

00000150h: 70 00 AC 0A C0 74 29 B4 0E BB 07 00 CD 10 EB F2 ; p.?纓)??.?腧

00000160h: 3B 16 18 7C 73 19 F7 36 18 7C FE C2 88 16 4F 7C ; ;..|s.?.|?O|

00000170h: 33 D2 F7 36 1A 7C 88 16 25 7C A3 4D 7C F8 C3 F9 ; 3吟6.|?%||?

00000180h: C3 B4 02 8B 16 4D 7C B1 06 D2 E6 0A 36 4F 7C 8B ; 么.?M|?益.6O|?

00000190h: CA 86 E9 8A 16 24 7C 8A 36 25 7C CD 13 C3 0D 0A ; 蕟閵.$|?%|??.

000001a0h: 4E 6F 6E 2D 53 79 73 74 65 6D 20 64 69 73 6B 20 ; Non-System disk

000001b0h: 6F 72 20 64 69 73 6B 20 65 72 72 6F 72 0D 0A 52 ; or disk error..R

000001c0h: 65 70 6C 61 63 65 20 61 6E 64 20 70 72 65 73 73 ; eplace and press

000001d0h: 20 61 6E 79 20 6B 65 79 20 77 68 65 6E 20 72 65 ;  any key when re

000001e0h: 61 64 79 0D 0A 00 49 4F 20 20 20 20 20 20 53 59 ; ady...IO      SY

000001f0h: 53 4D 53 44 4F 53 20 20 20 53 59 53 00 00 55 AA ; SMSDOS   SYS..U

这个块称为引导块,注意最后的55AA就是许多书上讲Linux启动时所谓的引导标志了,没有其它的内容可以分析的了。

接下来,我将对这个磁盘映象一个扇区一个扇区地分析了。

第二个扇区和第一个扇区一样属于引导块,这里就不列举出其内容了,这里的一块是两个扇区即1024B。接下来的一块就是大名鼎鼎的超级块了。其内容如下:

00000400h: E0 01 A0 05 01 00 01 00 13 00 00 00 00 1C 08 10 ; ??............

00000410h: 7F 13 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ...............

00000420h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................

00000430h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................

00000440h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................

00000450h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................

00000460h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................

后面一直到该磁盘块结束的地方全部都是0:

000007f0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................

下面列出这个超级块的结构:

struct super_block{

unsigned short s_ninodes; i节点数(1E0=480)

unsigned short s_nzones; 逻辑块数(5A0=1440刚好是软盘的容量)

unsigned short s_imap_blocks; i节点位图所占用的数据块数(1块)

unsigned short s_zmap_blocks; 逻辑块位图所占用的数据块数(1块)

unsigned short s_firstdatazone; 第一个数据逻辑块号(13H=19块)

unsigned short s_log_zone_size; log(数据块数/逻辑块)

unsigned long  s_max_size; 文件最大长度

unsigned short s_magic;  文件系统魔数(137F)

...//后面的成员仅出现在内存中,不列举出来。

这个superblock的信息就这么多,它表示该文件系统有480个i节点,逻辑块数是1440,每块是1024B,所以总容量就是软盘容量了。i节点位图和逻辑块位图都只占用一个数据块。第一个数据块块号是19号,这里存放的是"/"根文件了,等会儿就可以看到了。

接下来的一个磁盘块就是所谓的i节点位图块了,这已经是第3个磁盘块了。

00000800h: FF FF FF FF FF FF DD FF 7F 01 00 00 00 00 00 00 ; ???????.......

00000810h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................

00000820h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................

00000830h: 00 00 00 00 00 00 00 00 00 00 00 00 FF FF FF FF ; ............????

00000840h: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ; ????????????????

00000850h: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ; ????????????????

00000860h: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ; ????????????????

后面一直到该磁盘块结束的地方全部都是1:

00000bf0h: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ; ????????????????

这里到00000830h行0结束的地方,总共有60个字节,即480位,与超级块中的i节点数480吻合。这480个位中,为1的表示i节点在用,为0的表示空闲。

逻辑块位图的原理和i节点位图一模一样,这里省略其分析。到此已经分析完了4个磁盘块。

i节点即index node索引节点。接下来的是第五个磁盘块了,480个i节点,每个i节点占用32个字节,总共占用480*32/1024=15个磁盘块,现在再重新理清一下磁盘块的关系了:

0块:引导块,每块1024B

1块:超级块

2块:i节点位图

3块:逻辑块位图

4...18:i节点区块

19块:数据块,刚好和Linux文件系统分析之二中提到的数据块开始于第19块吻合。

下面分析第一个i节点,它位于块号为4的块中,即是第五块了。

00001000h: ED 41 00 00 80 00 00 00 9E AA 2E 84 00 08 13 00 ; 鞟..?..灙.?...

00001010h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................

为分析这二进制中的数据涵义,下面列出i节点结构,这个i节点其实就是表示根目录了。

struct d_inode{

unsigned short i_mode;

unsigned short i_uid;

unsigned long i_size;

unsigned long i_time;

unsigned char i_gid;

unsigned char i_nlinks;

unsigned short i_zone[9];

}

刚好是32个字节,

i_mode表示文件类型和属性,这里是41ED即0100.0001.1110.1101

见stat.h文件中的定义:

第一个四位0100表示这是一个目录文件,确实如此,这就是根目录。

接下来的三位000表示文件的属性,执行或搜索时是否设置uid

最后面的九位1.1110.1101表示rwxrwxrwx了,这个用过linux的都知道

i_uid为0000,表示这个文件的所有者的uid是0,通常root用户的uid就是0

i_size为00000080,表示这个文件的长度为80H=128个字节,后面可以验证。

i_time为842EAA9E,表示这个文件的创建时间

i_gid为00,表示该文件所有者所在group的id为0

i_nlinks为08,表示有8个文件目录项指向该i节点

最后一个13H即19表示该文件的数据块号,后面都是0,表示该文件在一个数据块中存得下,不用更多的数据块。

分析之四将追溯到这个i节点的数据块即19块,用以说明目录项的数据结构。

下面顺着分析之三的思路,追溯到19号磁盘块,首先算出其偏移地址19*1024=19456即4C00处,这里的磁盘映象如下:

00004c00h: 01 00 2E 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................

00004c10h: 01 00 2E 2E 00 00 00 00 00 00 00 00 00 00 00 00 ; ................

00004c20h: 02 00 62 69 6E 00 00 00 00 00 00 00 00 00 00 00 ; ..bin...........

00004c30h: 06 00 64 65 76 00 00 00 00 00 00 00 00 00 00 00 ; ..dev...........

00004c40h: 19 00 65 74 63 00 00 00 00 00 00 00 00 00 00 00 ; ..etc...........

00004c50h: 1E 00 75 73 72 00 00 00 00 00 00 00 00 00 00 00 ; ..usr...........

00004c60h: 3C 00 74 6D 70 00 00 00 00 00 00 00 00 00 00 00 ; <.tmp...........>

00004c70h: 44 00 72 6F 6F 74 00 00 00 00 00 00 00 00 00 00 ; D.root..........

00004c80h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; 该块后面都为0

这里每一行,即16个字节,表示一个目录项。

struct dir_entry{

unsigned short inode;

char name[NAME_LEN];

};

第一个目录项,4c00那一行中,inode为01,表示该目录所在i节点为第1个i节点,name为"."就是所谓的当前目录了"/",这个目录i节点确实

就是第一个,即我们在分析之三中分析的那个。

第二个目录项,inode为01,name为".."表示上一层目录,目前已是根目录了,上层目录也是根目录,这就是为什么在根目录时执行cd ..命令

时结果还是根目录。

第三个目录项,inode为02,name为"bin",它就表示/bin目录了。

后面的几个同理可知其涵义。如此,这个文件系统根目录下面有.,..,bin,dev,etc,usr,tmp,root这8个目录了,每个目录占用16个字

节,总共就占用了128个字节了,这个数字和分析之三中的i_size为128刚好吻合。

下面我们顺藤摸瓜,看看这个root目录下面有些什么东西。root位于第44H=68个i节点,在磁盘映象中找到如下:

00001860h: ED 41 00 00 20 00 00 00 00 58 9C 29 00 02 4D 05 ; 鞟.. ....X?..M.

00001870h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................

这个root目录的i节点显示其数据块在054DH=1357块中,即1357*1024=153400H处

00153400h: 44 00 2E 00 00 00 00 00 00 00 00 00 00 00 00 00 ; D...............

00153410h: 01 00 2E 2E 00 00 00 00 00 00 00 00 00 00 00 00 ; ................

除了两个.,..目录外这个目录下面什么也没有,可以看到.目录就是当前目录,其i节点为44,..指向根目录,而根目录i节点为01,和前面的

分析刚好吻合。

再看看usr目录下面有什么东西,usr位于第1EH=30个i节点,再磁盘映象中找到如下:

000013a0h: ED 41 00 00 50 00 00 00 80 79 73 29 00 05 95 01 ; 鞟..P...?ys)..?

000013b0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................

这个目录的i节点显示其数据块在0195H=405块中,即405*1024=414720=65400H处

00065400h: 1E 00 2E 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................

00065410h: 01 00 2E 2E 00 00 00 00 00 00 00 00 00 00 00 00 ; ................

00065420h: 1F 00 62 69 6E 00 00 00 00 00 00 00 00 00 00 00 ; ..bin...........

00065430h: 3B 00 6C 6F 63 61 6C 00 00 00 00 00 00 00 00 00 ; ;.local.........

00065440h: 3D 00 72 6F 6F 74 00 00 00 00 00 00 00 00 00 00 ; =.root..........

显然比root目录多了bin,local,root目录了,下面往该文件系统中写一个文件,看看通过这里的分析方法是否能够找到。

通过rootimage引导,往/usr/root目录下面写入hello.c文件,在分析之四中已经到达了/usr/root目录,在进一步看看这个目录里面有什么内容:

这个目录位于第3DH=61个i节点,再磁盘映象中找到如下:

00001780h: FF 41 00 00 50 00 00 00 48 A2 47 40 00 02 29 05 ; ?A..P...H@..).

00001790h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................

所以/usr/root目录的实际数据存放在0529H=1321块中,1321*1024=1352704=14A400H偏移地址处

0014a400h: 3D 00 2E 00 00 00 00 00 00 00 00 00 00 00 00 00 ; =...............

0014a410h: 1E 00 2E 2E 00 00 00 00 00 00 00 00 00 00 00 00 ; ................

0014a420h: 3E 00 2E 62 61 73 68 5F 68 69 73 74 6F 72 79 00 ; >..bash_history.

0014a430h: 42 00 61 2E 6F 75 74 00 00 00 00 00 00 00 00 00 ; B.a.out.........

0014a440h: 45 00 68 65 6C 6C 6F 2E 63 00 00 00 00 00 00 00 ; E.hello.c.......

0014a450h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................

还是老一套,同样有.,..目录,除此之外还有.bash_history,a.out,hello.c文件,就是我们写进去的文件了。该文件的i节点号为45H=69,找到此i节点:

00001880h: 80 81 00 00 4A 00 00 00 48 A2 47 40 00 01 9A 05 ; ??.J...H@..?

00001890h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................

这个i节点就是hello.c文件的i节点,这个文件的数据放在059AH=1434块中,1434*1024=1468416=166800H偏移地址处

00166800h: 23 69 6E 63 6C 75 64 65 20 3C 73 74 64 69 6F 2E ; #include

00166810h: 68 3E 0A 0A 69 6E 74 20 6D 61 69 6E 28 29 0A 7B ; h>..int main().{

00166820h: 0A 09 70 72 69 6E 74 66 28 22 48 65 6C 6C 6F 2C ; ..printf("Hello,

00166830h: 20 77 6F 72 6C 64 21 5C 6E 22 29 3B 0A 09 72 65 ;  world!/n");..re

00166840h: 74 75 72 6E 20 30 3B 0A 7D 0A 00 00 00 00 00 00 ; turn 0;.}.......

00166850h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................

00166860h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................

00166870h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................

这个hello.c就这样显身了。

在详细地看看这个i节点的内容,

i_mode是8180即1000.0001.1000.0000

第一个四位1000表示这是一个常规文件,接下来的三位000表示文件的属性,执行或搜索时是否设置uid

最后面的九位1.1000.0000表示rwxrwxrwx了,这是个文件主人可以读写,但是不能执行的文件,其它组或人都不能读写执行该文件。

i_uid为0000,表示这个文件的所有者是root

i_size为0000004A,表示这个文件的长度为74个字节,数一数,确实是74个字节。

i_nlinks为01,表示有1个文件目录项指向该i节点,可以创建链接ln再来看看这个是否为1。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值