iOS 10.3的APFS系统
BeaNorman
8年前
<p style="text-align:center"><img src="https://simg.open-open.com/show/4215abf1a4301ab426b8d10a6a5159a2.jpg"></p> <p>何为APFS</p> <p>在iOS 10.3中,苹果新增了APFS新文件系统,最早在2016年WWDC大会上公布。APFS是Apple File System的简称,用于替代目前所使用的HFS+格式。APFS对HFS的所有变体进行了统一,这是Apple从底层代码开始从零打造的全新文件系统。与使用32位文件ID的HFS+不同,APFS可支持64位索引节点(Inode)编号,借此一个卷最多可存储超过900亿亿个文件。HFS+只能同时对整个存储设备的文件系统进行初始化,APFS提供了一种可扩展存储块分配程序(Extensible block allocator),可对数据结构进行延迟初始化(Lazy initialization),进而大幅改善大容量卷的性能。</p> <p>APFS针对闪存/SSD存储进行优化(但依然可用于传统机械硬盘),提供了更强大的加密、写入时复制(Copy-on-write)元数据、空间分享、文件和目录克隆、快照、目录大小快速调整、原子级安全存储基元(Atomic safe-save primitives),以及改进的文件系统底层技术。此外APFS还包含其他改善和新功能,例如稀疏文件、改进的TRIM操作,内建对扩展属性的支持等。</p> <p>安全与隐私是APFS的设计基础。Apple的很多设备和操作系统早已具备加密功能,OS X 10.7 Lion开始提供全磁盘加密功能;iOS 4开始可通过专用数据保护技术将每个文件使用一个专用密钥进行加密。APFS对这两种功能进行整合,为文件系统元数据提供了一种统一的加密模式。APFS支持三种模式的加密:不加密;适用于元数据和用户数据的单密钥加密;以及适用于元数据、文件,甚至文件中特定部分的多密钥加密。多密钥加密功能,内置有针对每个文件的密钥,其针对敏感元数据也都有独立的密钥,在确保可靠性的基础上优化性能。多密钥加密可确保哪怕设备物理安全受到威胁,依然可以保障用户数据的完整性。取决于具体硬件,APFS加密可使用AES-XTS或AES-CBC算法。</p> <p>这种加密机制还实现了一个额外的功能:更为快速的数据擦除。通常情况下当用户从设备中删除文件后,可以通过市面上提供的很多(免费或收费的)反删除软件找回删掉的内容。为避免这种情况,以往如果需要删除包含机密信息的文件,或需要将存储过私密数据的设备退役给他人使用,必须首先使用抹掉功能擦除存储设备,并可能要将这一过程执行多遍。取决于存储设备容量,整个过程将耗费极多时间。对于使用APFS文件系统的存储设备,在启用加密功能后,安全擦除的过程将变得大为简便和快捷,不再需要耗费大量时间多次给存储设备填充随机数据,只需要删除加密所用的密钥即可。</p> <p>APFS包含一个名为“空间共享”的新功能,借助该功能,多个文件系统可以共享同一个物理卷上的同一块底层可用空间。也就是说,设备上的一个APFS“容器”内部可以包含多个“卷”(文件系统)。HFS+需要为每个文件系统预先分配固定大小的容量,这种做法较为“僵硬”,而APFS的空间共享功能可以让用户在无需重分区的情况下动态、灵活地扩大或缩小卷容量。在这样的设计下,APFS容器内的每个卷都会显示同等的可用空间容量,而所显示容量会等同于该容器的可用存储空间总量。例如,假设有个容量100GB的APFS容器,其中包含已用10GB容量的卷A和已用20GB容量的卷B,卷A和卷B都会显示自己有70GB(100GB-10GB-20GB)的可用容量。</p> <p>现代化的文件系统往往会通过压缩和去重(Deduplication)等方式减小文件占用的空间量。压缩很好理解,去重是指找出大量文件中相同的数据块,并只将这样的块存储一次,在访问文件时,会根据实际情况动态“拼装”出最终的文件。这样的功能最适合保存大量用户文件或大量虚拟机映像的服务器环境。APFS可以用恒定的速度对多个文件和目录创建副本。举例来说,如果要在同一个文件系统(或同一个容器)内部复制文件,实际上并不需要为数据创建副本,只需要对文件的元数据进行适当的更新就可以让磁盘上存储的数据实现“共享”,此时相同的文件“实际体积”不变,但产生了两个副本,对任何一个副本进行改动则需要为其分配新的存储空间(这种方式也叫做“写入时复制”)。APFS中复制的文件实际上只是对文件创建了轻量级克隆,实际数据并没有重复保存,底层设备的故障会导致所有“副本”受损。</p> <p>APFS专门针对闪存进行了优化。SSD虽然可以模拟传统机械硬盘的“块”,但底层技术与机械硬盘截然不同。SSD底层的管理工作是由一种名为闪存转换层(FTL,Flash Translation Layer)的软件负责处理的。FTL与文件系统极为类似,可以在块地址和介质内部的位置之间创建虚拟映射(转换)。整个堆栈,包括SSD、FTL,以及文件系统都由Apple控制,可以更有针对性地对不同组件进行优化。</p> <p>此外APFS还提供了对TRIM的支持。TRIM是ATA协议中的一个命令,可以让文件系统告诉SSD(其实是指示SSD中的FTL)某些空间是空闲的。可用空间越多,SSD的性能表现会越好,甚至大部分SSD所拥有的存储容量会超过标称值。假设有一个1TB容量的SSD,显示的可用空间总量为931GB。在有更多可用空间的情况下,FTL可以牺牲空间利用率换回更高性能和更长寿命。但TRIM的问题在于,只有在存在可用空间的情况下这个功能才会有用,如果磁盘即将装满,TRIM不会为你带来任何效果。</p> <p>性能方面,APFS的延迟也有了大幅改善。APFS可以通过I/O QoS(服务质量)对不同的访问请求划分优先级,将用户可以立刻察觉的操作和后台活动区分对待。计算机系统在任何时候都可能出故障:崩溃、Bug、断电等…… 文件系统必须能够预见到这种情况并从故障中顺利恢复。遇到这种情况,以前可能需要尝试着用专门的工具在系统启动前检查并修复文件系统(例如使用fsck)。较为现代化的系统会使用某些“始终一致”的格式,或将不一致的可能尽量降低,以避免耗费大量时间执行完整的fsck检查。例如ZFS就可以在磁盘上构建一个新状态,然后通过一次原子操作从之前的状态以原子级方式过度到新状态。</p> <p>校验是一种针对数据进行的摘要会汇总,可用于检测(和纠正)数据错误。APFS会对自己的元数据,而非用户数据进行校验。这种对元数据进行校验的做法理由非常充分:大部分元数据都与用户数据无关(因此校验不会耗费太多存储空间),而丢失元数据会有极大可能造成用户数据的丢失。距离来说,假设某个顶层目录的元数据出错,那么磁盘上的所有数据都有可能无法访问。也正是因此,ZFS会对元数据创建副本(甚至对顶层元数据创建三重副本)。</p> <p>但是完全不对用户数据进行校验,这种做法似乎更有趣。大部分可支持APFS的Apple设备中的SSD实际上是由多个或多或少相互独立的NAND芯片组成的。Apple设备的存储具备强大的ECC纠错保护。NAND闪存SSD和磁介质机械硬盘都可以使用冗余数据检测和纠正错误。NAND会使用额外的数据,例如每4KB页使用额外的128字节数据,借此检测和纠正数据错误。设备本身的误码率已经足够低,可以认为设备整个生命周期内都不会出现错误。还有一些设备错误可以通过文件系统的冗余机制避免。SSD中包含大量组件,而大部分消费类产品中的SSD很少包含端到端的ECC保护,因此可能导致数据传输过程中出现错误。SSD固件中也可能包含导致数据丢失的Bug。</p> <p>覆盖写入数据是最容易造成不一致的操作。如果文件系统需要覆写文件的多个区块,有一定可能遇到一些区块已经代表新状态,但一些区块依然代表旧的状态。为避免这种问题,可以使用上文提到的写入时复制这一方式,首先分配新区块,随后释放旧区块使其可被再次使用,而不需要就地修改数据。APFS实施了一种“全新的写入时复制元数据体系”,这种方式的新颖之处在于,APFS并未使用ZFS机制复制已更改用户数据的所有元数据,只需要对文件系统结构进行一次原子更新即可实现。</p> <p>APFS系统提升了苹果的iOS、macOS、watchOS及tvOS等平台的文件完整性与安全性。APFS系统启用后,大大缩减了系统的体积,升级到iOS 10.3系统后,可以使内置空间多出1GB的空间,对于老型号的机器是个很好的消息。</p> <p>根据Apple在WWDC上的介绍,APFS的核心设计目标是将数据加密作为头等要务,为现代化备份方式提供快照功能。但APFS也有些不尽如人意的地方,如:APFS不针对用户数据进行校验,没有提供数据冗余机制;无法用于启动磁盘,文件和目录名称大小写敏感,无法用于Time Machine、FileVault或Fusion驱动器;APFS文件系统的卷无法被OS X 10.11 Yosemite以及更早的版本识别等。但技术总是进步的,谁能说这些问题不会在不久的将来解决呢?我们拭目以待。</p> <p>早期的文件系统HFS+和UFS</p> <p>文件系统除了让用户供稳定地存放文件这一目标以外,还是各项操作系统功能的基础。Mac OS X每个大发行版都要增加数百项新功能,许多新功能严重依赖于文件系统的实现。</p> <ul> <li> <p>UFS</p> </li> </ul> <p>UFS是经典的Unix文件系统,HFS+和UFS文件系统同时被引入早期的Mac OS X。在Unix系统早期,文件系统被称为FS。FS包括启动块、超级块(处于硬盘分区开头用来保存文件系统信息)、inodes(索引节点)及数据,但FS会导致抖动等一系列问题。为了解决这些问题,产生了FFS(Fast File System)。FFS把先前整块的磁盘文件系统分为小块,每块包含自已的索引节点和数据,因而增加了文件的局部性,减少了寻道时间。Unix系统的各BSD分支(FreeBSD、OpenBSD、NetBSD及DragonFlyBSD)在FFS文件系统上增加各种扩展,但这些扩展往往不互相兼容,却又都使用和原版同样的块大小和数据块宽度,因此可以在一个操作系统上能对另一操作系统的文件系统执行只读操作。故它有了一个更广泛的称谓——UFS(Unix File System,即Unix文件系统)。</p> <p>后来,UFS提供了简单的日志功能。在档案系统发生变化时,先把相关的信息写入一个被称为日志的区域,然后再把变化写入主文件系统的文件系统。在文件系统发生故障(如内核崩溃或突然停电)时,日志文件系统更容易保持一致性,并且可以较快恢复。</p> <p>BSD的Soft Update功能,保证了计算机掉电或系统崩溃时,通过使元数据按依赖顺序更新来确保磁盘上总的文件系统保持一致的实现机制。Soft Update的目标和日志类似,实现代价比日志轻量许多,但却需要引入一个后台FSCK检查。基于对UFS的一项改进,为Soft Update加入了日志功能,并消除了对FSCK的依赖。</p> <p>先前,Unix文件系统的访问控制是非常简单的,其权限管理分为三个不同的类别:用户、同组用户以及其他用户,对每个类别,Unix文件系统提供读、写、执行三种权限的管理。这样的许可管理过于粗糙,无法指定某一用户访问的权限,也无法指定更为细致的权限内容(例如准许对一文件实行删除操作)。为解决这个问题,UFS增加了ACL访问控制表功能(Access Control Lists),访问控制表被增加到文件系统中,使用以存取控制矩阵为基础的存取控制方法。存取控制串列描述每一个文件对象各自的存取控制,并记录可对此物件进行存取的所有主体对对象的权限。总之,UFS与时俱进,不断增加新的功能。</p> <p>Mac OS X起源于NeXTSTEP,因为基于BSD,所以自然也使用UFS。</p> <ul> <li> <p>HFS+</p> </li> </ul> <p>在引入UFS的同时,Mac OS 还有个文件系统HFS,HFS诞生于1985年,为了实现Mac OS的现代化,在HFS的基础上,加入现代文件系统所必需的新功能,如大文件支持、Unicode文件名支持、长文件名支持、32位文件映射表支持等,同时也把HFS项目原本的Mac使用的68K处理器汇编码改写成C代码。即改进的HFS+文件系统。</p> <p>HFS+根植Mac OS,HFS+是对HFS的扩展,故HFS+支持Mac OS至Mac OS X的平滑过渡,所以Mac OS X一直默认使用HFS+,但当时的UFS提供比HFS+更先进的功能。Mac OS X 10.2.2开始,HFS+支持日志,带日志功能的HFS+(被称为HFSJ,即HFS+ volume with journal)成为默认设置。之后增加了名件名、目录名区分大小写及Unicode 3.2的支持。Mac OS X 10.4中,HFS+更是增加了ACL访问控制表功能,提供更复杂的对传统Unix文件系统权限的扩展。在Mac OS X 10.5之后HFS+成为唯一正式的Mac OS X系统,HFS+提供的功能也已超越UFS。</p> <p>在逐步的优化中,HFS+愈走愈远。</p> <ul> <li> <p>FileVault可以用来加密用户文件,因此用户主目录被保存在一个HFS+文件系统加密镜像中。Mac OS X 10.7提出了FileVault2,能加密整个磁盘而不是一个用户目录。</p> </li> <li> <p>Spotlight桌面搜寻搜索功能,能让用户对整个磁盘系统进行快速搜寻、随打即显。这项功能要求文件系统提供任意长度文件元数据(metadata)的支持。</p> </li> <li> <p>BootCamp需要时时调整系统主分区的大小,来空出磁盘空间给Windows,因此,HFS+又需要支持动态分区大小调整。</p> </li> <li> <p>Time Machine,是苹果公司所推出备份的工具程序,Time Machine对于修改过的文件会在备份盘上保存一个新拷贝,而对于不变的内容,仅在备份盘上存一个指向先前文件的硬链接。因此每一次快照只保存改动的文件,而别的文件只保存占用空间很少的硬链接。但Unix一般只支持文件的硬链接而不支持目录的硬链接。因此HFS+在这点上走得比Unix文件系统更远,提供了对于目录的硬链接支持。</p> </li> <li> <p>HFS+支持文件系统压缩,使得安装后占用比Mac OS X 10.5少得多的空间。</p> </li> </ul> <p>但,HFS+并不完美。</p> <p>不完美的文件系统</p> <p>经过长期发展,HFS+针对不同类型的设备衍生出不同功能的多种分支,但它毕竟太老、太混乱了。更重要的是,该文件系统不具备当今大多数企业所需要的一些基本功能,例如纳秒级时间戳、校验、快照、稀疏文件等。从1998年4GB容量的传统HDD机械硬盘,到现在TB规模的SSD固态硬盘,HFS+已经招架不住存储领域的大量改变和创新。</p> <p>HFS+基于B-树实现,当查找B-树中未使用的节点时,HFS+只能每次处理16位,原因是老Mac使用的Motorola的68K芯片原生支持16位的数据操作。但不管是PowerPC还是Intel,寄存器都支持256位宽的寄存器。</p> <p>HFS+的元数据(metadata)都以大字节序保存,原因是Motorola的68k和后来Mac使用的PowerPC都使用大字节序。但经过Intel迁移后,当今的Mac都使用Intel芯片,而Intel芯片是使用小字节序的。因此每当数据读取或存入时,还要经过小字节序和大字节序的转换。远古时期磁盘很慢,计算机处理器的速度也很低,因此进行一次磁盘操作会占用较多的时间,HFS+的时间分辨率为一秒,但当今的磁盘、处理器处理一次文件系统操作的时间远小于一秒,因此所有主流磁盘文件系统的时间分辨率都是一至数百纳秒级别的。</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/baffe9c86915e7be954fd5f23109eb81.png"></p> <p>HFS+的元数据有全局锁,同一时间只有一个进程可以访问更新文件系统。在单核处理器连手机平板都较少见到的当今,这种设计显得很幼稚。</p> <p>HFS+亦没有稀疏文件的支持。例如我们在SQL中建立了一个数据库,SQL分配了10GB的文件给这个数据库,并且在文件头和文件尾写上一些字节的数据。而由于我们还没有给这个数据库添加新的数据,所以这10GB的文件除了头尾外其他字节都为0。现代的文件系统基本都支持稀疏文件,也就是说,当处理这个数据库操作时,事实上往磁盘写入的数据只有那文件头和文件尾的若干字节。而HFS+则需要把那些0也写上,因此会完整写入10GB的数据,耗费长得多的时间。</p> <p>此外,HFS+不具备元数据校验功能、快照功能、写入时复制功能、就地执行功能、逻辑卷管理功能等很多现代磁盘系统所具备的功能,也不能动态调整文件块大小。这些功能的加入并不容易。这使得用户数据时时处于风险之中。例如由于因为断电、内核崩溃等原因,文件系统上写到一半的数据,小则导致个别文件损坏,大则导致整个文件系统崩溃。在生产领域,这样不可靠的文件系统,很有可能带来致命的灾难。</p> <p>快照功能可将文件系统的状态“固定”在创建快照的那一刻,并可在保留固定状态的同时继续访问和修改文件系统。这种技术可以只记录新增或改动的数据块,因此可以为文件系统创建多个快照,而无需担心会占用大量存储空间。备份工具(例如Time Machine)通常会使用该功能记录自从上次备份之后文件系统的改动情况,并可用于在不打断用户操作的前提下对数据进行更为高效的备份。</p> <p> </p> <p>来自:http://www.cocoachina.com/ios/20170227/18782.html</p> <p> </p>