Linux

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Linux GPT分区表16进制实例分析
Linux GPT分区表16进制实例分析
GPT分区表随着win10的普及,已经在越来越多的新电脑上开始使⽤了。

前段时间的新闻有看到说Intel会在后⾯的新平台中完全取
消CSM⽀持,这也⼤概相当于后⾯新出的Intel平台的主板将只有纯UEFI模式引导,Legacy模式没有了,也就是说必须要使⽤GPT分区了。

对于普通⽤户来说,GPT的好处最明显的地⽅就是⽀持系统分区⼤于 2TB,但这似乎并没有什么⽤(因为MBR并不⽀持单个分区⼤
于2TB)。

另外⼀个就是,GPT分区必须要⽤UEFI,⽽M$从win8开始搞了个SecureBoot,也能从⼀定程度上增加那么⼀丢丢安全性吧。

然⽽在服务器领域就不⼀样了,服务器的SAN存储很容易就能聚合出⼀个⼤于 2T的盘,甚⾄10多T⼀个LUN都是很常见的事情,尽管Linux下⾯有LVM可以绕过分区,但是作为未来的主流分区技术,GPT也将会变得很重要,还是有必要来从底层研究⼀下。

这篇⽂章我们使⽤的实验环境是这样的,VMWare虚拟机安装RHEL6.8,除开系统的虚拟硬盘VMDK之外,额外添加两块虚拟硬盘,⼀块5GB为/dev/sdb,另⼀块6GB为/dev/sdc。

通过解析这两块虚拟硬盘的分区表头的信息,结合GPT的官⽅⼿册,⽤例⼦来分析GPT分区表到底是怎么构成的。

需要说明的是,这篇⽂章我们的实验只对这两块虚拟硬盘作建⽴GPT分区表的操作,为避免⼲扰,先不建⽴分区。

-----------------------------------------------------------------------------
我们使⽤Linux⾃带的hexdump⼯具来从16进制的层⾯分析GPT分区表。

从上⾯的图中可以看到,我们的两块硬盘/dev/sdb和/dev/sdc分别为5GB和6GB,此时是刚添加了⼀块新的虚拟硬盘的状态,所以没有分区表,也没有分区,我们使⽤hexdump来读取这两块硬盘,可以看到⾥⾯的数据全都是0,这也符合是⼀块全新的硬盘的状态。

先来解释⼀下hexdump的这个输出结果。

每⼀⾏表⽰16Byte(字节)的数据,所以第⼀列的值就显⽰的是当前⾏是第多少个字节,它是
以16进制显⽰的。

中间那个星号(*)表⽰它代替的⾏的数据跟上⼀⾏是⼀样的(这将使得输出结果更易读)。

那么红框
中140000000和180000000的意思就很明显了,通过将16进制转换成10进制,140000000(Hex) = 5368709120(Dec),180000000(Hex) = 6442450944(Dec),5368709120/1024/1024/1024=5,6442450944/1024/1024/1024=6,结果刚好就是5GB和6GB,这也印证了上⾯说的第⼀列的数字表⽰的是当前⾏是第多少个字节。

140000000和180000000是最后⼀⾏,也就是硬盘能存储数据的最后的位置,也就表⽰硬盘的⼤⼩了。

-----------------------------------------------------------------------------
然后我们⽤parted⼯具,将这sdb和sdc建⽴⼀个gpt分区表。

parted /dev/sdb mklabel gpt & parted /dev/sdc mklabel gpt
分完区之后,再次使⽤hexdump读取硬盘,就有了上⾯截图的内容,可以发现,多了不少内容。

先来看GPT硬盘整个的硬盘结构⽰意图,这个图是来⾃UEFI Specifications⽂档,LBA0是Protective MBR,然后就是GPT分区表头,再接着就是每个分区的描述,这三部分构成了主GPT分区表。

从First useable block到Last useable block是给每个分区⽤于存储数据的。

最后还有⼀个备份的GPT分区表,是由每个分区的描述和分区表头构成。

根据UEFI Specifications⽂档,GPT分区表头是有两部分的,第⼀部分⼀般位于LBA1,另外还有⼀份alternate GPT,可以理解为备份的GPT表头,它位于硬盘的最后⼀个LBA。

⾄于LBA是怎么计算的,这⾥就不展开讲,⼀般来说,硬盘每个LBA是512Byte字节,所
以LBA0就是从0x00000000 到 0x00000200-1,⽽LBA1就是从0x00000200开始,⽤进制转换⼀下,200(Hex) = 512(Dec),就是512字节。

LBA0的Protective MBR部分这⾥就不讲了,有兴趣的可以去看官⽅⽂档,这篇⽂章只关⼼GPT分区表的结构。

GPT的分区表头,是从LBA1开始的,长度⼀般为92字节,结合UEFI Specifications和Wikipedia维基百科,根据hexdump的输出结果,我们来⼀⾏⼀⾏地分析⼀下sdb的GPT分区表主表头。

00000200 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
字节:GPT Signature,它是⼀串ASCII码字符串“EFI PART”,把这8个16进制数45 46 49 20 50 41 52 54分别转换成10进制,就是69 70 0-8字节
73 32 80 65 82 84,去查⼀下ASCII码表,它就是字符串“EFI PART”,注意两个单词中间还有个空格。

字节:GPT修订版本,表⽰是1.0版,即00 00 01 00。

9-11字节
字节:GPT分区表头⼤⼩,⼀般是92字节,也就是16进制数5c,即5c 00 00 00。

12-15字节
00000210 47 f1 8d 83 00 00 00 00 01 00 00 00 00 00 00 00 |G...............|
16-19字节
字节:GPT头部共92字节数据的CRC32校验值,计算该CRC32值时把这4个字节先置为0再计算,计算完成之后,再将计算出来的值填⼊这4个字节。

我们来计算⼀下。

先把hexdump输出结果的92个字节摘出来,再把16-19字节全填成0,就是下⾯这样:
45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00
00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00
ff ff 9f 00 00 00 00 00 22 00 00 00 00 00 00 00
de ff 9f 00 00 00 00 00 dd 25 f8 96 c6 47 56 4f
aa ed c2 48 bd ee 50 7d 02 00 00 00 00 00 00 00
80 00 00 00 80 00 00 00 86 d2 54 ab
可以看到,这个结果跟hexdump显⽰的16-19字节数据⼀致,即47 f1 8d 83。

字节:保留位,必须为0。

20-23字节
字节:当前GPT表头所在的LBA,上⾯说到主GPT表⼀般是LBA1,所以结果是01,即01 00 00 00 00 00 00 00。

24-31字节
00000220 ff ff 9f 00 00 00 00 00 22 00 00 00 00 00 00 00 |........".......|
字节:Alternate GPT表头所在的LBA,上⾯说到这个⼀般是最后⼀个LBA,也就是硬盘的最后⼀个512字节,这个值是怎么算出来的32-39字节
呢?/dev/sdb容量⼤⼩是140000000(Hex) = 5368709120(Dec),除于512字节,5368709120/512 = 10485760(Dec),就是这个硬盘的
总LBA数,因为是最后⼀个LBA所以再减1,即10485760-1 = 10485759(Dec) = 9FFFFF(Hex),
ff ff 9f 00 00 00 00 00
字节:第⼀个可⽤的LBA,根据UEFI官⽅⽂档规定,LBA⼤⼩为512字节时,第⼀个可⽤的LBA必须要⼤于或等于34,即34(Dec) = 40-47字节
22(Hex),即22 00 00 00 00 00 00 00。

00000230 de ff 9f 00 00 00 00 00 dd 25 f8 96 c6 47 56 4f |.........%...GVO|
00000240 aa ed c2 48 bd ee 50 7d 02 00 00 00 00 00 00 00 |...H..P}........|
字节:最后⼀个可⽤的LBA,跟上⾯的第⼀个可⽤LBA同样的道理,就是最后⼀个LBA-34,/dev/sdb容量⼤⼩是140000000(Hex) = 48-55字节
5368709120(Dec),5368709120/512 = 10485760(Dec),10485760 - 34 = 10485726(Dec) = 9FFFDE,即de ff 9f 00 00 00 00 00。

字节:硬盘的GUID,这个值是唯⼀的,不可重复。

56-71字节
字节:定义GPT分区⼊⼝的LBA,就是LBA1+1=LBA2,即02 00 00 00 00 00 00 00。

72-79字节
00000250 80 00 00 00 80 00 00 00 86 d2 54 ab 00 00 00 00 |..........T.....|
字节:定义的分区⼊⼝的数量,80(Hex) = 128(Dec),128个分区。

即80 00 00 00。

80-83字节
字节:每个分区⼊⼝的⼤⼩,⼀般是80(Hex) = 128(Dec),即80 00 00 00。

84-87字节
字节:分区⼊⼝列表的CRC32校验值。

88-92字节
-----------------------------------------------------------------------------
上⾯就是主GPT分区表头的16进制逐⾏分析,下⾯就是备份分区表头部分了,根据上⾯的分区,备份的分区表头位置是在硬盘的最后⼀
个LBA,即140000000(Hex) = 5368709120(Dec),5368709120/512 - 1 = 10485759(Dec),10485759 * 512 = 5368708608(Dec) =
13FFFFE00(Hex),即截图中最后⼀部分的备份GPT分区表头的起码位置。

通过⽐较主表头和备份表头,我们发现有如下⼏个地⽅不⼀样:
1、16-19字节的GPT头部共92字节数据的CRC32校验值,这个CRC32校验值不⼀样是由于24-31字节(当前GPT表头所在的LBA)和32-39字节(备份GPT表头所在的LBA)的位置正好是跟主表头位置相反引起的。

2、24-31字节(当前GPT表头所在的LBA)和32-39字节(备份GPT表头所在的LBA),这两个值刚好跟主GPT表头的值是相反的,即互为主备。

3、72-79字节GPT分区⼊⼝的LBA,备份表头肯定指向的备份的分区⼊⼝列表的LBA。

除了上述3个地⽅不⼀样之外,其它地⽅跟主GPT表头完全⼀致。

-----------------------------------------------------------------------------
然后我们在/dev/sdb上创建两个分区,再看分区表会有什么样的变化。

[root@RHEL68 ~]# parted /dev/sdb mkpart sdb1 1 100M
[root@RHEL68 ~]# parted /dev/sdb mkpart sdb2 100M 300M
跟未分区时候相⽐,多了两个分区⼊⼝,这些分区⼊⼝在官⽅⽂档中被称为GPT Partition Entry Array。

分区表头部分和未分区相⽐,有两个地⽅发⽣了变化,⼀个是16-19字节的GPT头部共92字节数据的CRC32校验值,这个值发⽣了变化是因为88-92字节分区⼊⼝列表
的CRC32校验这个发⽣了变化,因为多了两个分区,所以分区⼊⼝列表的CRC32校验值肯定会发⽣变化。

第⼀个分区的⼊⼝起始位置是0x400,第⼆个分区⼊⼝起始位置是0x480,所以每个分区⼊⼝描述长度是80(Hex) = 128(Dec) Byte。


个128byte其实已经在表头⾥⾯有定义过的,上⾯有说过,就是表头的84-87字节。

每个分区的⼊⼝描述根据官⽅⽂档是这样定义的,见下图。

下⾯来分析第⼀个分区的分区⼊⼝描述。

00000400 a2 a0 d0 eb e5 b9 33 44 87 c0 68 b6 b7 26 99 c7 |......3D..h..&..|
00000410 84 b3 41 ef 05 e6 c1 43 8e 61 bb 5b 4f f9 a9 28 |..A....C.a.[O..(|
字节:分区唯⼀标识符,跟分区表头定义的硬盘GUID⼀个道理,也必须是唯⼀值。

16-31字节
00000420 00 08 00 00 00 00 00 00 ff f7 02 00 00 00 00 00 |................|
32-39字节
字节:分区起始LBA,也就是800(Hex) = 2048(Dec),分区真正开始使⽤是2048*512 = 1048576(Dec) = 100000(Hex)。

字节:分区结束LBA,也就是2F7FF(Hex) = 194559(Dec),分区的最后⼀个LBA的起始字节数是 194559*512 = 99614208(Dec) = 40-47字节
5EFFE00(Hex),还要加上⼀个LBA即512字节,即5F00000(Hex),也就是下⼀个分区的起始字节数。

00000430 00 00 00 00 00 00 00 00 73 00 64 00 62 00 31 00 |........s.d.b.1.|
00000440 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
字节:属性标识符,保留的。

48-55字节
字节:分区名称,共72字节。

本例中,为0073(Hex),0064(Hex),0062(Hex),0031(Hex),转换到10进制,就是115(Dec), 56-127字节
100(Dec), 98(Dec), 49(Dec),查询⼀下ASCII码,即sdb1。

相关文档
最新文档