转至 http://www.linuxdiyf.com/bbs/thread-197157-1-1.html
首先说明硬盘的物理组成。整个硬盘的物理组成主要有:
1| 圆形的盘片(记录数据的部分)
2| 机械手臂与在其上的磁头(读写盘片上的数据)
3| 主轴马达(转动盘片让磁头读写)
下面以几何数学抽象分析一个硬盘。硬盘是一个圆柱体。它被切成250个圆片,对应每个圆片有一个磁头,从上至下编号[0-254]。再看编号为0的第一个圆片,按固定大小将它分成一个个圆环,叫磁道,由外至内编号[0-n]。所有圆片以此规则给磁道编号。再看编号为0的磁道,它以每512bytes一份分成了63等分,规定一起始位置,依次编号为[1-63]。所有磁道以此规则给扇区编号。这每512bytes的区域叫扇区。再看整个圆柱体,所有编号为0的磁道作为一组磁道柱,叫柱面(窃以为翻译为“柱面”并不好。)。从上往下看,这个圆柱体就是由编号[0-n]的柱面组成的。一磁道的大小为:63*512bytes。一个柱面的大小为:255*63*512bytes=7.8M。这就是著明的C/H/S模型(cylinder/Header/Sector)。这样,每一组C/H/S数据与每一扇区一一对应。这种模型并不好,所以Linux不用,DOS使用它的。
还有另一种数学模型,就是LBA(Logical Block Addressing)模型。 它对应于C/H/S模型,以0/0/1所对应的扇区开始,将所有扇区依次以自然数序列编号为[0-n ]。
实际的硬盘一到二个盘片就够了,不过却是通过上面讲的数学模型来进行存取的。下面是关于硬盘分区的内容。
硬盘的第一个扇区,叫MBR,全称为Master BootRecord,即硬盘的主引导记录。这一扇区也叫主引导扇区。在总共512bytes的主引导扇区里,主引导程序(bootloader)占446bytes,第二部分是Partitiontable区(分区表),即DPT,占64个bytes,记录硬盘的分区情况。第三部分是magicnumber,占2个字节,固定为55AA,起标记分区表的作用。
通常情况,至少在Linux下的文件系统格式,以MBR所在磁道的下一磁道,也就是0柱面/1磁头/1扇区(LBA的63号扇区,就是第64格)作为各个分区的开始,这样既保护MBR所在磁道,又可以让各分区的起始/末尾都在柱面的边缘(除了第一个分区),不过ms粗暴的从0/0/2作为第一个分区的开始。一般情况硬盘内部的逻辑结构可以描述为:
[硬盘]=[[第一磁道][分区组]]
[第一磁道]=[[MBR ][剩余62扇区]]
由于分区表总量是64bytes。需要以每16bytes记录一个分区的信息。所以它最多只能记录四笔分区记录,与我们想建立多于四个分区的现实不符,于是出现了扩展分区的概念。0号扇区里存放着4或少于4个分区的记录,其中一个可以是扩展分区,并且不能多于一个。
扩展分区的里的分区叫逻辑分区。扩展分区的第一个扇区同样用来存放分区表,只是这的分区表更像是一单链链表。每个扩展分区的分区表只记录两笔记录:一条隶属于自己的逻辑分区记录,另一条指向下一个逻辑分区的记录,我认为可以形象比喻为拿一串一次性水杯环环半套着,以杯底为扩展分区之首,杯口为末,这样整条杯子链就是一扩展分区。每个杯子的杯底半部分就是自己的逻辑分区,同时是前一杯子的扩展分区;杯口半部分就是自己的扩展分区。其逻辑形式为:
[扩展分区一]=[[第一磁道][逻辑分区一][扩展分区组]]
[扩展分区k]=[[第一磁道][逻辑分区k ]](当k>1)
[第一磁道]=[[分区表 ][剩余62扇区]]
我希望我已经讲明白扩展分区的概念了,并希我并没有理解错。原本14点多的时候,这篇文章快完工了,正准备去上课呢,刚好这时候分析数据的时候发现扩展分区并不是原来理解的那样,回这修改的时候,又不那么好说明白。一开始我以为扩展分区里是子扩展分区的概念,每个子扩展分区包含接下来的所有分区。后来认为每个子扩展分区包含连续的两个分区。最后得出现在的这个结论。
下面通过工具dd与losetup模拟出一个硬盘,然后用cfdisk分区,并分析它的分区表,来深刻理解硬盘的分区。
# touch /tmp/mydisk
# cd /tmp/
# dd if=/dev/null of=mydisk count=1 seek=4000000
# modprobe loop
# losetup /dev/loop0 mydisk
这样,就可以把文件mydisk当作一个硬盘来使用了。下面对它进行分区。
# cfdisk -h 255 -s 63 /dev/loop0
一个主分区,一个扩展分区,扩展分区内分了三个逻辑分区。下面分析它们的分区表,用# cfdisk -P r /dev/loop0就可以看到它们的分区表,我们先看MBR里的信息。
Sector 0:
0x000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x110: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x120: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x130: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x140: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x150: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x160: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x170: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x190: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 01
0x1C0:01 00 17 FE 3F 1B 3F 00 00 00 DD DC 06 00 00 00
0x1D0: 01 1C 05 FE 3F F7 1C DD 06 00 DC ED 35 00 00 00
0x1E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA
我们已经知道MBR里有446bytes的主引导程序,64bytes的分区表和2bytes的“55AA”分区表标志。由于这个硬盘里没有主引导程序,所以[0x000-0x1BD ]的引导程序代码为零。[0x1BE-0x1FD]里就是分区表。可以表示4项分区,每项分区为16个字节。我们只要把16个字节的内容搞清楚了,分区表就不再神秘了。(用bc的ibase=16;obase=10来快速转进制数)
MBR是分区表的信息只有两项内容:
80 0101 00 17 FE 3F 1B 3F 00 00 00 DD DC 06 00
00 0001 1C 05 FE 3F F7 1C DD 06 00 DC ED 35 00
这意味着MBR的分区表中只定义了两个分区,我们一个一个来分析,先分析第一个分区表项,80 0101 00 17 FE 3F 1B 3F 00 00 00 DD DC 06 00,我们先解释一下这16个字节的含义。
第一个字节的内容是分区的引导标志,80表示是引导分区,00表示不是引导分区。接下来三字节表示分区的起始磁头、扇区、柱面,本例中三个参数分别是01 01 00,这代表第一个分区从0柱面1磁头1扇区开始。第五个字节表示分区类型,17表示某类型,常用的类型有0F(扩展分区),0B(FAT32),06(FAT16)。接下来三字节分别表示分区的结束磁头,扇区,柱面。注意,这里有些玄机,分区的起始扇区和结束扇区看起来用了一个完整字节,其实不是。由于C/H/S中扇区编号从1到63,因此用一个字节表示有些浪费,一个字节由八个二进制数组成,扇区编号只用了低六位,高2位给柱面用了。因此,表示柱面其实用了10个二进制数,其中高2位是从扇区参数中借来的。结合本例看看,这三参数分别是 FE3F1B,分析一下,FE表示分区的结束磁头是254,3F拆为二进制是00111111,低六位是111111,用来表示分区的结束扇区,也就是说结束扇区是63。FF拆开后高2位00给了柱面用,不过柱面还是1B,结束在27/254/63。
C/H/S的柱面用了10个二进制数,最多只能表示1024个柱面,也就是说最多只能表示1024X7.8M=7.8G大小的硬盘,这之后的硬盘容量它就力不从心了。这也是当初设计分区表时目光短浅,如果能用两个字节表示柱面,那现在就完全没问题了。由于C/H/S对现在的海量硬盘根本无用武之地,因此表示分区大小的重任就只能落在LBA的肩上了。后八个字节就是用LBA方法来表示分区距起始的位置和分区大小,这个起始位置是相对于本分区表所在扇区来说的,起始位置+分区大小-1=结束位置。
本例中这四个字节的内容是3F 00 00 00,首先我们要高低位互换,四个字节的内容是00 00 003F,转为10进制是63,这意味着第一个分区之前的扇区数是63,也意味着第一个分区从63扇区开始。因为LBA表示扇区是从0开始编号而不是从1开始,分区之前有63个扇区意味着分区之前的扇区是从0到62,那分区起始自然应该从63开始。
最后四位参数是DD DC 06 00,高低位转换后得:06 DC DD,转为10进制是449757。知道了分区起始位置在63,大小为449757,就可以算得结束位置为63+449757-1=449819
对分区表的第一个项内容总结一下,这16个参数告诉我们,第一个分区从0/1/1开始,到27/254/63结束,可以引导系统,分区类型为某类型,分区起始的扇区数是63,分区大小是449757扇区。
接下来的分析就不看C/H/S的起未了,因为超8G的它表现不了,不过这上面的数据是通过LBA计算得来的。
分析第二项00 0001 1C 05 FE 3F F7 1C DD 06 00 DC ED 35 00
知道:不可引导;分区类型为扩展分区(05);距起始扇区449820(06 DD 1C );分区大小3534300(35 EDDC)。得这个分区的末尾是3974119.接下来要分析的第二张分区表就是在扩展分区的第一个扇区449820扇区里。截取分区表部分:
Sector 449820:
0x1B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 01
0x1C0: 01 1C 83 FE 3F 37 3F 00 00 00 DD DC 06 00 00 00
0x1D0: 01 38 05 FE 3F 53 1C DD 06 00 1C DD 06 00 00 00
0x1E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA
这个分区表同样只定义了两个分区,通过前面的概念,知道一个是逻辑分区一,后一个扩展分区二(补充:实际也就是逻辑分区二加上其前的一磁道。),下面分析一下它的数据。
分析第一项知道:不可引导;分区类型代码83;距起始扇区63(00 00 00 3F);大小449757(06 DCDD)。这个起始扇区不是从整个硬盘开始算的,而是从本扩展分区的位置开始算的,所有这个数值基本都是63。于是这个起始扇区实际是449820+63=449883;结束扇区是449883+449757-1=899639。这一组起始/结束数据就是逻辑分区一的位置。
分析第二项:不可引导;类型为扩展分区(05).距起始扇区449820(06 DD 1C)大小449820(06 DD 1C).注意:以后向下定义后续扩展分区时,之前的扇区数指的都是被定义的扩展分区的起点到第一个扩展分区起点的距离。得起始在扇区449820+449820=899640;结束扇区在899640+449820-1=1349459。这一组数据其实就是逻辑分区二加其前面的一磁道所有的位置。下面分析在扇区899640里边的分区表。
Sector 899640:
0x1B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01
0x1C0: 01 38 83 FE 3F 53 3F 00 00 00 DD DC 06 00 00 00
0x1D0: 01 54 05 FE 3F F7 38 BA 0D 00 A4 33 28 00 00 00
0x1E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 0055 AA
分析第一项:不可引导;分区类型83;距起始扇区63(00 00 00 3F)分区大小449757(00 06 DCDD);得这个分区起始在扇区899640+63=899703;结束在899703+449757-1=1349459。正是上一个扩展分区的位置减去首磁道。
分析第二项:不可引导;分区类型扩展分区(05);距起始扇区899640(0D BA 38)分区大小2634660(0028 33A4);注意:前面提到过了,这个起始是相对于第一扩展分区起始的,而不是相对于前一个扩展分区的。得这个分区起始在扇区449820+899640=134960;结束在1799280+2634660-1=4433939。下面看最后一张分区表,因为其后再没有扩展分区,所以它就只有本逻辑分区的一条记录。
Sector 1349460:
0x1B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01
0x1C0: 01 54 83 FE 3F F7 3F 00 00 00 65 33 28 00 00 00
0x1D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA
分析得:不可引导;分区类型83;起始63;大小2634597;得起始扇区为:1349460+63=135523;结束在135523+2634597-1=3984119
至此,分区表分析完毕。分析它只是为了更好的理解硬盘的分区规律,而这些数据完全可以通过工具获得。
# cfdisk -P t /dev/loop0
Partition Table for /dev/loop0
---Starting---- ----Ending----- Start Number of
# Flags Head Sect Cyl ID Head Sect Cyl Sector Sectors
-- ----- ---- ---- ----- ---- ---- ---- ----- ----------- -----------
1 0x80 1 1 0 0x17 254 63 27 63 449757
2 0x00 0 1 28 0x05 254 63 247 449820 3534300
3 0x00 0 0 0 0x00 0 0 0 0 0
4 0x00 0 0 0 0x00 0 0 0 0 0
5 0x00 1 1 28 0x83 254 63 55 63 449757
6 0x00 1 1 56 0x83 254 63 83 63 449757
7 0x00 1 1 84 0x83 254 63 247 63 2634597
# cfdisk -P s /dev/loop0
Partition Table for /dev/loop0
First Last
# Type Sector Sector Offset Length Filesystem Type (ID) Flag
-- ------- ----------- ----------- ------ ----------- -------------------- ----
1 Primary 0 449819 63 449820 Hidden HPFS/NTF (17) Boot
2 Primary 449820 3984119 0 3534300 Extended (05) None
5 Logical 449820 899639 63 449820 Linux (83) None
6 Logical 899640 1349459 63 449820 Linux (83) None
7 Logical 1349460 3984119 63 2634660 Linux (83) None
理解之后,如果分区表丢失,恢复数据只要将分区表复制到相应位置就可以了。即使所有的分区表都不见了,也是可以恢复的。每个分区在建立文件系统时,都会将本分区的类型,大小等信息放在这个分区的头上。研究这个,我们还是可以确定当前这个分区在硬盘上的位置。有了这个位置信息,基本上还是可以大致的恢复出整个硬盘的分区表(有些信息不太能确定,比如说到底是主分区还是逻辑分区)。如果文件系统的信息也丢失了呢?那就只能碰运气了。运气好的话,你能找到一些系统在隐含扇区备份的分区表信息。你可以全盘查找55AA这个特征值,然后看它像不像分区表。