从程序员角度理解磁盘分区(MBR和GPT)

写在前面

应该很多人和我一样,对磁盘分区都有个感性的认识,其中不乏熟练使用分区工具的人。

但是分区的本质是什么呢? 这个问题看似简单,但是很少人能给出完美的答案!

我自己在学习上有个习惯,那就是没有亲身去看到实实在在的数据,就很难去掌握一个抽象的概念!我比较讨厌填鸭式的教学,例如网上绝大多数文章会告诉你传统MBR分区的一个分区极限大小是2TB,但是原因很少有人告诉你,这就比较让人恼火了。

因此我提倡不管学习什么都要触及本质,只有这样才会真正理解掌握它们!

本文先介绍分区的概念,然后介绍两个主流的磁盘分区方案,即MBR分区和GPT分区。然后借助linux下的fdisk工具实际操作分区,最后自己写测试程序来读取分区。这个过程中就会真实地看到分区内容,尤其最后的写程序阶段,要将抽象的概念具体结构化,这样就再也不会忘记了,也不用刻意去记什么2TB大小限制了,因为这个大小限制是由实际的数据结构大小限制的,一切成了理所当然。

介绍下我的试验环境:Ubuntu 17.04,fdisk程序是util-linux里的一个工具,版本是2.29。这里需要说明一下的是,fdisk的老版本是不支持GPT分区的,但是现在的新版本已经支持了,具体从哪个版本开始的,我也不清楚。

另外,本文中的代码和文档我都已经放在github上了(https://github.com/astrotycoon/learn_MBR_and_GPT)。

 

分区的概念

分区的作用是把一个物理存储设备分割成多个不同的逻辑上的存储设备。对于windows系统来说,表现的结果就是不同的盘符,对于linux系统来说就是不同的挂载点。要注意,分区不是一个操作系统的概念(Disk partitioning)。

分区的本质是往磁盘分区表中写入特定的数据来告诉操作系统这个磁盘被逻辑上分割成了几个存储区域,是对磁盘大小的妥善分割利用,不同的分区之间好像有了一道“城墙”, 起到了物理隔绝的效果。分区表(Partition table)格式是规定好的,只要在分区表中写入正确的数据,就可以对设备分区。

至于分区内部的的格式,这个是由各个操作系统自己决定的,NTFS/FAT/EXT2这些都指的是分区内部的数据结构,它们是与分区表无关的。也就是说一般分区后,我们可以通过格式化相应的分区为某个文件系统来管理文件。这就是磁盘格式化的概念,它是指根据用户选定的文件系统在磁盘的特定分区写入特定数据,一般都是分区中划出一片用于存放文件分配表、目录表等用于文件管理的磁盘空间,剩余空间则存储实际的文件内容。通过这些我们可以得出结论:文件系统是基于一个完整的分区的

另外,分区有什么好处吗?

硬盘分区就像给一间空荡的房子划分出卧室,厨房,客厅等相互隔离的空间一样。主要是为了方便用户的使用。另一方面,通过合理的硬盘分区,有效保护系统盘空间,确实能够提高系统运行速度,再者,硬盘分区也可以有效地对数据进行保护。你当然可以不分区,只不过,当你面对越来越多的子目录,或者是越来越慢的Windows,不得不费功夫去管理你的文件,或者重装Windows的时候,恐怕会悔不当初。 “不要把所有的鸡蛋放在同一个篮子里”这句至理名言在经济学以外的其他领域也同样是句警世恒言。

此外分区的好处还有可以让我们安装多个操作系统,使用不同的文件系统等等。

 

MBR分区方案

MBR分区方案存在很多年了,始于上世纪80年代。

MBR分区方案的方法是将分区表写在硬盘0柱面0磁道1扇区偏移446字节处,总共64个字节大小,每个分区表占用16字节。好,直接上代码,看下这16字节是如何定义的:

struct dos_partition {
    uint8_t boot_ind;       /* 引导标志:0x80 - 活动分区 0x00 -- 非活动分区 */
    uint8_t bh, bs, bc;     /* 起始CHS */
    uint8_t sys_ind;        /* 分区类型 */
    uint8_t eh, es, ec;     /* 结束CHS */
    uint8_t start_sect[4];  /* 分区起始LBA地址 */
    uint8_t nr_sects[4];    /* 分区所占扇区总数 */
} __attribute__((packed));        

 

 

 

 

 

 

GPT分区方案

参考链接:

《GPT 分区详解》

《安装 Linux 时碰到的硬盘分区的陷阱及应对》

你可能感兴趣的:(工具学习)