Chinaunix首页 | 论坛 | 博客
  • 博客访问: 156008
  • 博文数量: 24
  • 博客积分: 59
  • 博客等级: 大尉
  • 技术积分: 192
  • 用 户 组: 普通用户
  • 注册时间: 2008-12-20 13:10
文章分类

全部博文(24)

文章存档

2012年(1)

2011年(2)

2009年(19)

2008年(2)

我的朋友

分类: LINUX

2009-02-18 18:03:28

[转] 教你认识分区表

当你看到下面的fdisk 输出信息,你能想到什么呢?

Disk /dev/sda: 120.0 GB, 120034123776 bytes
255 heads, 63 sectors/track, 14593 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0x00000080
   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *           1        5099    40957686    7  HPFS/NTFS
/dev/sda2            5100       11473    51199155    f  W95 Ext'd (LBA)
/dev/sda3           11474       12542     8586742+  83  Linux
/dev/sda4           12543       14593    16474657+  83  Linux
/dev/sda5            5100       10198    40957686    7  HPFS/NTFS
/dev/sda6           10199       11473    10241406    b  W95 FAT32

没错,它们表示的是硬盘的各个分区的起始柱面,结束柱面,分区大小,分区类型以及分区是否可以引导。
柱面信息是近似的。真正精确表示分区起始,终止位置的是硬盘的扇区位置。比如:
Disk /dev/sda: 120.0 GB, 120034123776 bytes
255 heads, 63 sectors/track, 14593 cylinders, total 234441648 sectors
Units = sectors of 1 * 512 = 512 bytes
Disk identifier: 0x00000080
   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *          63    81915434    40957686    7  HPFS/NTFS
/dev/sda2        81915435   184313744    51199155    f  W95 Ext'd (LBA)
/dev/sda3       184313745   201487229     8586742+  83  Linux
/dev/sda4       201487230   234436544    16474657+  83  Linux
/dev/sda5        81915498   163830869    40957686    7  HPFS/NTFS
/dev/sda6       163830933   184313744    10241406    b  W95 FAT32

这些扇区的位置精确表示了各个分区的信息。有个这个信息,以后即使不小心删除了分区,我们还是可以用上面的信息来还原所有硬盘分区。

要了解整个过程,我们必须了解分区表信息在硬盘扇区上是如何存放的。
OK,接下来,我们在Linux下面做一个小小的试验。

一:搭建一个分析硬盘分区表的环境。
1:建立一个虚拟的硬盘。
不得不承认,Linux是个好东西。虚拟硬盘是如此的简单。

   user@pclinux: dd if=/dev/null of=diskb seek=2097152 count=0 bs=1024

或者,头个懒,用qemu-img,怎么也可以少敲几个字母,:)。
   user@pclinux: qemu-img create diskb 2G

到目前为止,diskb还只是一个文件。我们可以利用loop设备,将它模拟成一个硬盘。
   user@pclinux: sudo losetup /dev/loop0 diskb

好了,现在loop0就是diskb对应的硬盘了。
2:开始分区。
我把整个diskb成一个FAT32主分区,一个扩展分区。在扩展分区里边建立一个FAT32的逻辑分区。分区表如下:
Disk /dev/loop0: 2147 MB, 2147483648 bytes
255 heads, 63 sectors/track, 261 cylinders, total 4194304 sectors
Units = sectors of 1 * 512 = 512 bytes
Disk identifier: 0xe89bd33e
      Device Boot      Start         End      Blocks   Id  System
/dev/loop0p1              63      417689      208813+   c  W95 FAT32 (LBA)
/dev/loop0p2          417690     4192964     1887637+   5  Extended
/dev/loop0p5          417753      835379      208813+   c  W95 FAT32 (LBA)

主分区和逻辑分区都不能引导。

3:用hexedit/dd等工具来分析分区表。
硬盘的访问模式有两种,一种叫CHS方式,一种是LBA方式。CHS方式比较古老。它是沿袭硬盘的物理方式来访问硬盘的。也就是说,如果要访问硬盘的某个逻辑扇区,它要先确定这个扇区所在的柱面(Cylinder),然后,在这个柱面上确定该扇区所在的磁头(Header),最后,在该磁头上,确定这个逻辑扇区。CHS方式访问大容量硬盘。大容量的硬盘都是按照LBA方式访问的。LBA将整个硬盘看成一串扇区数组。其中0号扇区着MBR和硬盘的主分区表。
我们先把0号扇区搞下来:

user@pclinux: sudo dd if=/dev/loop0 of=boot0.bin bs=512 count=1
user@pclinux: hexedit -s boot0.bin
00000000   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000010   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000020   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000030   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000040   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000050   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000060   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000070   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000080   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000090   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
000000A0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
000000B0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
000000C0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
000000D0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
000000E0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
000000F0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000100   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000110   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000120   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000130   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000140   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000150   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000160   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000170   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000180   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000190   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
000001A0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
000001B0   00 00 00 00 00 00 00 00  3E D3 9B E8 00 00 00 01  ........>.......
000001C0   01 00 0C FE 3F 19 3F 00  00 00 5B 5F 06 00 00 00  ....?.?...[_....
000001D0   01 1A 05 FE 7F 04 9A 5F  06 00 2B 9B 39 00 00 00  ......._..+.9...
000001E0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
000001F0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 AA  ..............U.

由于这个diskb并没有主引导程序,所以从0字节开始,所有引导代码为零。主分区表信息从偏移0x1be开始,一直最后倒数第三个字节结束(64字节) 。最后的55AA是标志位。

这64个字节分成4部分,每个16字节。描述了整个硬盘的主分区和整个扩展分区的信息。从这里我们可以看到,硬盘只能有4个主分区。这16个字节的含义如下:

字节           含义                             值
00          分区是否可引导。                    0,不可引导。80,可引导
01-03     分区开始的CHS值(Head,Sector,Cylinder,Sector的高 位是Cylinder的第9,10位)  
04          分区类型                            7,NTFS,C, FAT32,5,F 扩展分区等等
05-07     分区结束的CHS值(Head,Sector,Cylinder,Sector的高 位是Cylinder的第9,10位)  
08-11       LBA方式下,相对的起始扇区号
                在MBR分区里边,相对0扇区,
                 扩展分区表示相对于扩展分区的起
                 始扇区(little endion 格式)
12-15      该分区拥有的扇区数量 (little endion)

OK,回到我们的diskb,我们可以从这张分区表看到,diskb的第一个分区是类型C(FAT32)的主分区。它从硬盘的63个扇区开始(3f 00 00 00),一共有0x065f5b个扇区,本分区不可引导(00)。Diskb的第二个扇区是一个扩展分区,起始地址是0x065f9a,共有扇区0x399b2b个。

据我分析,CHS的值和LBA表示的逻辑扇区是可以相互转换的。大概是:
CHS==>LBA
Value of Cylinder *每柱的磁道数*每磁道的扇区数+ Value of Header * 每磁道扇区数 + Value of Sector = 结束扇区LBA 扇区值+1。

验证一下:
上面的FAT32分区结束CHS值为:0x19 0xFE 0x3F,那么,该分区结束扇区的LBA值应该是:
0x19*255*63+0xFE*63+0x3F-1 = 417689
上面的分区告诉我们,这个分区占有0x00065f5b个扇区,那么它的结束LBA值应该是:0x00065f5b+63-1
=417689
结果正确。(柱面和磁道编号是从零开始,而扇区是从1开始的。)

那么反过来,如果知道LBA值是不是也可以推算CHS值?
试一下:
Value of Cyliner = ( Value of LBA+1)/每柱磁道数/每磁道扇区数. 如果整除,柱面数减1。
Value of Header = ( Value of LBA+1 – Value of Cylinder * 每柱磁道数字 * 每磁道扇区数 ) / 磁道扇区数,如果整除,磁头数减1。
Value of Sector 依次类推。

(417689+1)/255/63 = 0x1A ,整除,减1,变成0x19.
(417689 +1 – 0x19*255*63)/63=0xFF,整除,减1,变成0xFE
(417689 +1 – 0x19*255*63 – 0xfe*63)=0x3F
Very Good,结果正是我们想的。

接着看下面的分区表,MBR所在的分区告诉我们,下一个分区是扩展分区,它的LBA起始地址是417690,也就是上面的0x065f9a。我们把它dump出来看看

user@pclinux : sudo dd if=/dev/loop0 of=ext_fat skip=417690 bs=512 count=1

验证一下:
user@pclinux: hexedit -s ext_fat
00000000   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000010   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000020   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000030   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000040   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000050   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000060   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000070   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000080   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000090   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
000000A0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
000000B0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
000000C0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
000000D0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
000000E0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
000000F0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000100   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000110   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000120   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000130   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000140   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000150   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000160   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000170   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000180   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000190   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
000001A0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
000001B0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 01  ................
000001C0   01 1A 0C FE 3F 33 3F 00  00 00 5B 5F 06 00 00 00  ....?3?...[_....
000001D0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
000001E0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
000001F0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 AA  ..............U.

这个扩展分区里边只有一个为C(FAT32)的逻辑分区,逻辑分区的起始地址在:417690+63处。
一共有扇区0x065f5b个。
Ok,到此,硬盘的两个分区表就已经搞清楚了。

如果分区表不小心丢失,想恢复的话,那就简单了。将这两个分区表复制到相应的位置就可以了。

简单的看一个复杂一点的例子:

Disk /dev/loop0: 6442 MB, 6442450944 bytes
255 heads, 63 sectors/track, 783 cylinders, total 12582912 sectors
Units = sectors of 1 * 512 = 512 bytes
Disk identifier: 0x1009e660
      Device Boot      Start         End      Blocks   Id  System
/dev/loop0p1              63     1606499      803218+  83  Linux
/dev/loop0p2         1606500    12578894     5486197+   5  Extended
/dev/loop0p5         1606563     3212999      803218+  83  Linux
/dev/loop0p6         3213063     4819499      803218+  83  Linux
/dev/loop0p7         4819563     6425999      803218+  83  Linux
/dev/loop0p8         6426063    11245499     2409718+  83  Linux
/dev/loop0p9        11245563    12578894      666666   83  Linux

上面的硬盘被分成1个主分区,5个逻辑分区,从这个表中,我们就可以看出整个硬盘所有分区表的位置了(很明显,这个硬盘被完全分区了,没有空白区)。
Name                            offset of LBA sector
FAT1                            0
FAT2                            1606500
FAT3                            3213000
FAT4                            4819500
FAT5                            6426000
FAT6                            11245500

6个扇区都不可引导。
大家用hexedit来验证。

备份的时候可以生成一个自己定义的格式,比较方便的一种为:

aa bb cc dd + FAT Sector
...

其中aa bb cc dd 是FAT Sector的LBA扇区号的16进制。这样,恢复的时候就非常方便了。
也许有人已经看出来了,最简单的备份/恢复就是利用fdisk的信息了。从根本上来说知道各个分区的大小,起始位置也就完全知道了整个硬盘的分区情况了。

如果不小心把所有的分区表都删掉了怎么办?是不是就不能恢复了呢?
放心,还是可以的。每个分区在建立文件系统时,都会将本分区的类型,大小等信息放在这个分区的头上。研究这个,我们还是可以确定当前这个分区在硬盘上的位置。有了这个位置信息,基本上还是可以大致的恢复出整个硬盘的分区表(有些信息不太能确定,比如说到底是主分区还是逻辑分区)。如果文件系统的信息也丢失了呢?那就只能碰运气了。运气好的话,你能找到一些系统在隐含扇区备份的分区表信息。你可以全盘查找55AA这个特征值,然后看它像不像分区表。

最后套用一句口号:”不抛弃,不放弃“。即使软件提醒你找不到分区表,别灰心,手工在处理一下。Windows用winhex, Linux用hexedit,也许能找到点希望。

阅读(3391) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~