FAT文件系统与UEFI

FAT文件系统与UEFI

小故事
传说,古印度有一个人发明了一种游戏棋,棋盘共64格,玩起来十分新奇、有趣。他把这种棋献给了国王。国王玩得十分开心,便下令赏赐献棋人。臣下问献棋人想要什么。献棋人说:"他只需要粮食,要求大王给点粮食便心满意足了。"问他需要多少粮食,他说只要求在棋盘的第一个格子里放一粒米,在第二个格子放两粒米,第三个格子里放四粒米??总之,后面格子里的米都比它前一格增大一倍,把64格都放满了就行。国王一听,满口答应。大臣们也都认为:这点米,算得了什么,便领献棋人去领米。岂料,到后来把所有仓库里的存米都付出了,还是不够。1立方米麦粒大约有1500万粒,那么照这样计算,得给那位献棋人12000亿立方米,这些麦子比全世界2000年生产的麦子的总和还多。

这个故事也许是杜撰的,但是也让我们见识了指数级增长的可怕力量。现代人作为洞穴人的后裔,总是以线性思维思考这个世界。去年打了三斤粮食,今年辛苦一点,多开垦了一成土地,多打了一成粮食,然后就盘算着明年能不能再上升一成。我们总是以线性思维思考周围的事物,规划未来发展,甚至会反映到我们程序架构中。然而,摩尔定律却指出科技发展是指数级增长的,发展会越来越快,超乎你我想象。我们在程序架构中的小小设定,当时看起来是十分合理的。太大多浪费空间啊,在我的有生之年这个设定都可以满足,今后的事情还是留给今后的人去处理吧。

然而,也许几年之后,我们甚至还没有离开原来的公司,就不得不处理不够用的问题。我们如热锅上的蚂蚁一样四处打着恼人的补丁,处理各种兼容性问题,还给后来人留下了饭后的笑谈。FAT的发展就是这样的故事。

FAT的原理

FAT得名于它的文件分配表(File Allocation Tables)方式,即在存储空间最开始有个大表,记录所有的可用块的使用链,并标记空闲块和坏块。一起来看个例子:


目录指出FILE1占用了0002块,系统查看文件分配表,0002链接到0003,0003链接到0004,0004链接到FFFF,说明是最后一块。所以文件系统知道,FILE1占用了0002,0003,0004这3块存储空间。简单而直接,不是吗?但它也有很多问题:

1. FAT表和后来的备份FAT表固定存储在开始位置。这意味着这里会被频繁读写,从而极易损坏,如果损坏了整个空间即为不可用,需要专业人士才能恢复部分数据。(当年把薄薄的5寸盘插入驱动器,在一阵吱吱声过后,报告0磁道的消息跳了出来,欲哭无泪的情形又浮现眼前)。延伸阅读:谁知道为什么SD卡等等NAND设备还要用FAT,不怕被写坏固定block?( 提示:FTL。先挖个坑,今后有时间再介绍NOR/NAND Flash和其上的文件系统和FTL)

2. 健壮性差。读写文件过程中经常需要更新FAT表,更新过程中发生意外断电等等轻的造成文件丢失,严重整个磁盘内容丢失。补救的办法就是把备份FAT复制到FAT。曾经潇洒地在DOS下迅速敲入一行命令,救mm磁盘于水火,而后在一众美女的注视下挥手离去,不带走一片云(JIAN)彩(QING)。。。。。

3. FAT表的大小已经被限定。从而可以支持的空间大小由块可以由多少个Bit来表示和每块的大小来决定。我们的狗血FAT历史也从这里开始。

FAT历史

1977年比尔盖茨还是个穷小子。他和Marc McDonald一起捣鼓出BASIC系统,叫做Standalone Disk BASIC-80,可以运行在8080的机器上。他们还为存储BASIC系统和程序,发明了最初的FAT,FAT表中表示下个链的位数(簇号)只有8位,用于支持8英寸的磁盘。

到了1980年,盖茨的好运来了。IBM希望为它的8086个人台式机(PC)寻找个新的操作系统。盖茨包下了这个任务,成立了微软公司,这个系统就是传说中的DOS。Tim Paterson改善了FAT原型,将磁盘存储正式变成下图:


文件名格式也变成CP/M(什么鬼?这是个暴露年龄的问题,向能不google而回答的同学脱帽致敬)兼容的8.3形式。他的一项最重要改动是将分区表项簇号从8位扩展为12位,能够支持的存储空间达到8MB!对比下当时不到20KB的磁盘,简直是绰绰有余。这就是FAT12。

很快硬盘到来了,几十MB的空间让FAT12变得十分可笑。微软不得不在1987年推出DOS3.3。他们大胆的将12位扩展为16位:FAT16,并通过增大每个sector的大小,从而可以支持多达2GB的空间!那是多达几百个硬盘的容量,这下总够用了吧!微软顺便加上了长文件名的支持。

计划赶不上变化,存储技术飞速发展,2GB很快不够用了,微软也希望在新版的Windows中提供亮眼的技术,FAT16兼容FAT12的问题让它伤透了心,希望能够避免犯下同样的错误。在1996年Windows 95 OSR2(带有MS-DOS 7.1),FAT32被发布了。簇号一下子从16位扩展为32位!(我也要指数级增长!)后来每簇表示的空间业扩至512kb,从而支撑最大达到2^41=2TB的容量,而当时最大的硬盘也只有1G!可以支持2048个硬盘叠在一起!

讽刺的是,连当时最大胆的举动也只为微软换来了不到10年的和平。磁盘大小的压力和现代文件系统理念的引入催生了NTFS。微软后期也在限制FAT32的使用,大于32GB的移动介质如U盘等都推荐采用exFAT了(感谢上帝不是简单粗暴的FAT64。exFAT加入了很多对于移动设备的支持,它不在本文范围内),硬盘也推荐NTFS。

FAT与UEFI

UEFI规定UEFI系统分区EFI system partition (ESP)采用FAT32格式,同时支持FAT12/FAT16作为移动介质的文件系统。UEFI的FAT分区和普通的FAT分区有个比较小的区别,即OSType不同。ESP在GPT(不再本文范围内)分区表中有个特殊的GUID:

C12A7328-F81F-11D2-BA4B-00A0C93EC93B

如果你用UEFI安装了Windows , 用windows自带的磁盘管理工具打开磁盘,你会发现有两个很小的隐藏分区。一个叫ESP(EFI系统分区),另一个MSR(Microsoft保留分区,通常为128MB)。MSR是windows要求的。ESP对UEFI启动很重要,UEFI的操作系统引导程序是以后缀名为.efi的文件存放在ESP分区中的,启动操作系统本质上就是运行ESP分区内的app:bootloader而已。各种操作系统的Bootloader各有不同,甚至可以混合放在一起,做成双启动或多启动,但其存放位置都应该符合UEFI spec的规定,详见Welcome to Unified Extensible Firmware Interface Forum. 大家想看看里面的内容,可以在UEFI shell下。如果不熟悉或者不方便,也可以在磁盘管理程序里将UEFI分区的隐藏属性去掉,这样你就可以在文件管理器(explore)里看到它们了,不过切忌修改(当然专家除外)。

需要澄清一下,ESP不是必须和GPT绑定的,也可以是MBR。只不过我们安装UEFI Windows时,总是要求我们使用GPT分区,才会导致这种误解。通过特殊的手段,MBR也可以用ESP启动UEFI OS,有兴趣的同学可以自行尝试一下。

后记

看了前面的文章,有的同学可能会有疑问: UEFI分区采用FAT32,会不会也有size不够用的问题啊?其实,UEFI分区内仅仅存储各种bootloader和BIOS错误恢复程序,操作系统和数据本身是不放在这里的,完全没有问题。

也有同学好奇UEFI为什么采用落后的FAT而不是当时已经存在的基于日志的现代文件系统,原因有好几个,大家可以仔细思考一下,稍后会公布。

GPT分区的内容参见:MBR与GPT - 知乎专栏

欢迎大家关注本专栏和用微信扫描下方二维码加入微信公众号"UEFIBlog",在那里有最新的文章。同时欢迎大家给本专栏和公众号投稿!

用微信扫描二维码加入UEFIBlog公众号
编辑于 2017-10-28

文章被以下专栏收录