APFS 文件系统探究

news2024/11/24 22:56:38

本文的创作初衷是因为我发现从底层详解 APFS 的资料很少,所以自己来进行了一些探究和整理。

一点说明

如果你在看 APFS 的文档或者其他内容,不要把高层级的分区理解成 Windows 中的分区。因为 APFS 里卷(Volume)才是显示在“访达”中的,在硬盘和卷之间还有一个容器的概念,一个容器可以包含多个卷,这不好和 Windows 中的分区概念对应。

APFS大致结构

APFS 内部结构大致如下:

APFS大致结构

上图只有一个卷,然后描述了这个卷中的各部分信息。其中“Storage for objects and file data”中的“objects”就包含了我们在访达中看到的那个存储硬盘,也就是一个卷。

“GUID partition table”的缩写便是很多人在 Windows 上熟知的 GPT(不是那个聊天机器人),而 GPT 分区则是 EFI 技术的一部分(EFI 又名为 UEFI,是 Intel 发明的)。

APFS 的每个容器是按照顺序排列在硬盘里的,并不会有空隙,这与 Windows 的 GPT 分区不一样。

APFS 的空闲空间是在各个卷之间共同分享的,所以扩展起来很容易

这也是为什么 Windows 上你只能扩展或调整最后一个分区的大小,而不能调整前面的盘(APFS 的空闲空间是在各个卷之间共同分享的,所以扩展起来很容易,如下图)。以及为什么 macOS 上新建 APFS 分区的时候需要很久很久(因为要把其他分区的文件挪到合适的地方)。

但系统是怎么知道硬盘上有这个容器的呢?顺序读取的话,第一个容器按顺序读下去就行了,但是第二个呢?

首先,系统不是通过顺序读取来发现容器的。而这些工作是硬盘最开始的 GUID partition table 的任务了,这部分会包含各个分区的起始和终止地址,用的时候跳转就行了,是一种目录式的结构。如下图(源自官方标准《GUID Partition Table (GPT) Disk Layout》):
https://uefi.org/specs/UEFI/2.10/05_GUID_Partition_Table_Format.html

可以看到通过主要分区表或者备用分区表划分分区以及进行跳转。

如果你查看 APFS 格式硬盘的十六进制的话,就可以看到如下情况(需要注意“GPT Header”部分是从200那行开始的):

请添加图片描述

可以看到内部开头的结构与其他 UEFI 格式的差不多。

Protective MBR

APFS 与其他一些 GPT 分区的文件系统不同的是:不论是不是启动盘,都会有 Protective MBR 部分。

Protective MBR 必须是使用 GPT 分区的硬盘上第一个逻辑块。这个分区的存在使得计算机认为这个硬盘是可以使用的,并且已被使用,就不会弹出弹窗问你需不需要进行分区、格式化等操作,EFI 本身是不会使用这个块的。

Protective MBR 部分如下:
请添加图片描述

各部分内容含义如下(偏移量是从这部分开头开始算,而且也是十六进制的):

部分字节偏移量字节长度内容
启动码0440EFI不会使用这部分,440的十六进制就是1b8,所以可以看到上图中1b8和之前的部分全部是00
唯一MBR硬盘签名4404没有被使用,设置为0
未知4442没有被使用,设置为0
分区记录44616*4四个MBR分区记录的数组。MBR最多就 4 个分区。
签名5102设置为0xAA55,也就是图中的1f0那行最后的55 aa
保留块512逻辑块大小-512逻辑块的剩余保留部分,设置为0

如果你对上面左侧的序号有疑问,需要记住这是十六进制的。比如说,最后的512的十六进制便是200

GPT Header

GPT Header 是 UEFI 技术和 GPT 分区的核心部分,这部分存储了很多信息。GPT Header 各部分如下:

请添加图片描述

各部分内容含义如下(偏移量是从这部分开头开始算):

部分字节偏移量字节长度内容
签名08这部分是 ASCII 格式的字符串“EFI PART”,用 64 位编码,也就是上图中的45 46 49 20 50 41 52 54
修正版本84GPT Header 的修正版本数,这个版本不等于 UEFI 指定版本。上文中的00 00 01 00表示是版本 1.0
Header 尺寸124GPT Header 的尺寸,单位是字节。这部分必须大于等于 92,小于等于逻辑块大小。上面的5C 00 00 00表示 92 个字节,也就是最小尺寸。上图只有 60 个字节,是因为省略了最后的几个空行
Header的CRC32164GPT Header 结构的 CRC32 校验和。先将这个值设置为 0,然后计算 GPT Header 结构的 32 位 CRC32 校验和,这里的校验和是15 51 0f ff
保留部分204这部分必须全部为 0
MyLBA部分248这个 LBA(逻辑块地址)包含数据结构,验证 GPT 的时候会检查 MyLBA 实例指向的 GUID Partition Table 中的 LBA,上图中为01 00 00 00 00 00 00 00
AlternateLBA328备用 GPT Header 的 LBA 地址,上图中为ff ff bf 46 07 00 00 00
第一个可使用LBA408GUID Partition Entry描述的一个分区的第一个被使用的可使用逻辑块,上图中为22 00 00 00 00 00 00 00
最后一个可使用488GUID Partition Entry描述的一个分区的最后一个被使用的可使用逻辑块,上图中为de ff bf 46 07 00 00 00
硬盘GUID5616标识硬盘的 GUID,上图中为84 ec 00 4a 8e 8c fd 47 8a 78 25 48 bf a4 90 99
分区实例 LBA728GUID分区实例数组的开始 LBA,上图中为02 00 00 00 00 00 00 00
分区实例的数量804GUID分区实例数组中分区实例的数量,上图中为80 00 00 00,也就是 8 个
分区实例的尺寸844GUID分区实例数组中GUID分区实例结构体的尺寸,这部分应该设置成128 x 2n的大小,n是大于等于0的整数,这部分一般是 128、256 等,但是早期的版本允许8的任意倍数。上图中的80 00 00 00实际上就是十六进制的80,也就是 128 个字节
分区实例数组的CRC32884GUID分区实例数组的 CRC32
保留92剩下所有保留块,全部为 0

GPT Partition Entry Array

GPT 分区实例数组(GPT Partition Entry Array)包含一个数组,这个数组存储了 GPT 分区实例。依旧先说明每个部分是什么,下面是 GPT 分区实例数组中的第一个实例:

请添加图片描述

部分字节偏移量字节长度内容
分区类型 GUID016定义分区目标和类型的唯一ID。如果分区没有被使用,那么这部分为 0。上图中为:28 73 2a c1 1f f8 d2 11 ba 4b 00 a0 c9 3e c9 3b,关于这部分的每个比特背后的含义后面细说
唯一分区 GUID1616每个分区实例唯一的 GUID。每个分区被创建时都会有这样一个唯一的 GUID,这个 GUID 也必须在 GPT 分区实例创建时分配值。上图中分配的为f8 56 1c 99 8d 6f 9e 4f bb fa 01 ca 52 57 cc 05
起始 LBA328这个实例中定义的分区起始 LBA
终点 LBA408这个实例中定义的分区终点 LBA
属性488这些属性位全部被 UEFI 保留,所以这里全部都是00 00 00 00 00 00 00 00
分区名称5672一个包含人类可读名称的无终止符字符。由于这是一个 EFI 分区,所以显示的是EFI System Partition
保留区域128之前设置的大小 ~ 128这部分必须为 0

根据操作系统的不同、分区的不同,分区类型 GUID 的值也是不同的。比如说上面的这个 EFI 系统分区的 GUID 值就是28 73 2a c1 1f f8 d2 11 ba 4b 00 a0 c9 3e c9 3b。有时你在其他资料里会看到是这样的:C12A7328-F81F-11D2-BA4B-00A0C93EC93B,这里每个-分隔开每个部分,加之上图中的值为小端数,你可以对应看看是一样的。

而 APFS 分区的分区类型 GUID 是ef 57 34 7c 00 00 aa 11 aa 11 00 30 65 43 ec ac,或者说7C3457EF-0000-11AA-AA11-00306543ECAC

上面“属性”中每部分的含义如下:

名称含义
0请求分区如果设置了这一位,那么必须有这个分区才能使平台运行,删除或修改这个分区的内容可能会导致平台功能丢失、无法启动或运行。所以除非操作系统、软件或固件能识别这个分区,否则不应该删除或修改这个分区。
1没有块IO传输协议如果设置了此位,那么固件不能为此分区生成EFI_BLOCK_IO_PROTOCOL部分,不设置这部分,那么就不会在 UEFI 中为该分区创建文件系统的映射
2传统 BIOS 可启动这位留给具有传统 PC-AT BIOS 固件的系统实现通知特定受限的、特殊目标的软件运行在一个可用 GPT 分区启动的系统上
3~47未定义,必须为 0,保留给未来的 UEFI 规范的扩展
48~63保留给 GUID 特定用途使用。这些位的使用根据分区类型 GUID 而设定。如果修改了 0~47 位中的任何一位,那么都必须保留这些位

可以看到,在 GPT 分区实例数组中的每个实例中,都标出了起始和终止点,于是就通过这些部分进行跳转和获取。

参考资料和扩展阅读

如果你想尝试查看上面的内容,那么可以按照我的这篇博客进行操作:《如何在Mac终端上,用十六进制查看某个硬盘(使用dd和hexdump,所以其他系统也可以使用这个方法)》。

关于 APFS 格式的实现细节可以参阅苹果对这篇文档:《Apple File System Reference》(“Apple File System”就是 APFS 的全称)。

UEFI 官方文档为:《GUID Partition Table (GPT) Disk Layout》。

《数据恢复技术深度揭秘(第二版)》刘伟编著。

希望能帮到有需要的人~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/876656.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

实战——OPenPose讲解及代码实现

一些前提 先思考下面几个问题; 1、什么是姿态估计? 参考:Point Detect任务,识别人体指定部分的关键点; 2、姿态估计中的难点是什么? 从干扰的角度,人体被遮挡对检测的影响很大;…

【枚举倍数+容斥】CF803 F

Problem - F - Codeforces 题意: 思路: 正难则反,考虑容斥 即考虑gcd ! 1的所有子序列个数 因为子序列内部无序,因此不算真正的子序列,考虑枚举倍数 根据经典套路,我们去枚举 gcd,然后去枚…

【枚举gcd】CF803 C

Problem - C - Codeforces 题意: 思路: 要使所有数的 gcd 尽可能大 设 gcd k 那么就是 k1 * k,k2 * k,k3 * k,.... 它们的和是n 那么(k1 k2 k3 ....) * k n 根据惯用套路,我们去枚举 n 的因子即…

Vue3 setup tsx 子组件向父组件传值 emit

需求:Vue3 setup 父组件向子组件传值,子组件接收父组件传入的值;子组件向父组件传值,父组件接收的子组件传递的值。 父组件:parent.tsx: import { defineComponent, ref, reactive } from vue; import To…

使用GUI Guider工具开发嵌入式GUI应用 (3) - 使用label组件

使用GUI Guider工具开发嵌入式GUI应用 (3) - 使用label组件 文章目录 使用GUI Guider工具开发嵌入式GUI应用 (3) - 使用label组件引言在GUI Guider工程中创建label组件编译MCU工程并下载到开发板 引言 本节讲述在GUI Guider中,应用各种UI的基本元素,并顺…

信创领航,合作共赢 | GBASE南大通用广州天河产业信创联盟协会交流分享会

参与本次会议的成员有: 广州天河信创产业联盟秘书长林坚武、广州天河科技园信息产业联合会秘书长王飞、北明软件事业部总经理周丽娟、盛祺信息副总经理闫建、天亿马营销中心总经理梁志杰、观必达总经理缪明宝、省信息工程资源部总监周燕莉、高科信息生态总监王晖、…

Dubbo基于springboot学习笔记

本文参考:【优极限】最透彻的Dubbo教程(dubbo经典之作完整版),阿里分布式框架dubbo零基础实战教学_手把手地啊你读懂底层源码【完整版】_哔哩哔哩_bilibili 1、 互联网架构演变 (1)单一应用架构 把系统中…

CentOS 8 非编译方式 yum 安装 FFmpeg

FFmpeg 是一套免费的开源计算机程序,它提供了录制、转换以及流化音视频的完整解决方案。FFmpeg 在 Linux 平台下开发,但它同样也可以在其它操作系统环境中编译运行,包括 Windows、Mac OS X 等。大多数文章都是说的ubuntu上如何安装&#xff0…

测试架构师如何落地性能测试方案(一)

背景描述: 最近刚接手一个新项目,在最开始的时候要求对这个项目做性能测试,产品经理也给不出性能需求,只因为这个项目是电商项目,可能会有高并发,秒杀的场景,所以产品经理要求我们对这个项目必…

亿发创新中医药信息化解决方案,自动化煎煮+调剂,打造智能中药房

传统中医药行业逐步复兴,同时互联网科技和人工智能等信息科技助力中医药行业逐步实现数字化转型。利用互联网、物联网、大数据等科技,实现现代科学与传统中医药的结合,提供智能配方颗粒调配系统、中药自动化调剂系统、中药煎配智能管理系统、…

前后端分离------后端创建笔记(05)用户列表查询接口(下)

本文章转载于【SpringBootVue】全网最简单但实用的前后端分离项目实战笔记 - 前端_大菜007的博客-CSDN博客 仅用于学习和讨论,如有侵权请联系 源码:https://gitee.com/green_vegetables/x-admin-project.git 素材:https://pan.baidu.com/s/…

2023年国赛数学建模思路 - 案例:感知机原理剖析及实现

文章目录 1 感知机的直观理解2 感知机的数学角度3 代码实现 4 建模资料 # 0 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 1 感知机的直观理解 感知机应该属于机器学习算法中最简单的一种算法,其…

类对象数组抽取对象指定属性重新组成新的类对象数组

原本后台返回数据是这样: 我只想要每条数据对象的jianyanneirong和jianyannneirong1两个属性的信息: 1.使用map方法 //contentList是原本类对象数组let a contentList.map((val)>{return {jianyanneirong: val.jianyanneirong,jianyanneirong1: val.…

【EI/SCOPUS检索】第三届计算机视觉、应用与算法国际学术会议(CVAA 2023)

第三届计算机视觉、应用与算法国际学术会议(CVAA 2023) The 3rd International Conference on Computer Vision, Application and Algorithm 2023年第三届计算机视觉、应用与算法国际学术会议(CVAA 2023)主要围绕计算机视觉、计算机应用、计…

展会邀请 | 虹科诚邀您参加8月16日深圳视觉系统设计技术会议

VisionCon视觉系统设计技术会议 将于8月16日在深圳深铁皇冠假日酒店隆重举行! 人力成本的提高、国际关系的不确定性等众多因素,都在促使中国制造业采用更先进的自动化及智能化技术,同时也在加速核心技术的国产化。作为智能制造不可或缺的关…

机器学习笔记 - 在 Vision Transformer 中可视化注意力

2022 年,视觉变换器(ViT) 成为卷积神经网络(CNN) 的有力竞争对手,后者现已成为计算机视觉领域的最先进技术,并广泛应用于许多图像识别应用中。在计算效率和准确性方面,ViT 模型超过了当前最先进的 (CNN) 几乎四倍。 一、视觉转换器 (ViT) 如何工作? 视觉转换器模型的性能…

VictoriaMetrics部署及vmalert集成钉钉告警

1、部署VictoriaMetrics cd /usr/local wget https://github.com/VictoriaMetrics/VictoriaMetrics/releases/download/v1.65.0/victoria-metrics-amd64-v1.65.0.tar.gz mkdir victoria-metrics && tar -xvzf victoria-metrics-amd64-v1.65.0.tar.gz && \ mv …

python_PyQt5运行股票研究python方法工具V1.1_增加表格展示控件

承接 【python_PyQt5运行股票研究python方法工具V1.0】 地址 python_PyQt5运行股票研究python方法工具V1.0_程序猿与金融与科技的博客-CSDN博客 目录 结果展示: 代码: 示例py文件代码(计算股票日横截面数据) 参数json文件 表…

Java SPI机制

Java SPI机制 java的spi就是一种服务提供发现机制,在一方制定好接口规范后,通过spi的机制可以它的子实现类进行服务发现,以及加载它的子实现类,通过这种机制,让我们在引入第三方库时,不用讲第三方库中的类…

Dubbo 核心概念和架构

以上是 Dubbo 的工作原理图,从抽象架构上分为两层:服务治理抽象控制面 和 Dubbo 数据面 。 服务治理控制面。服务治理控制面不是特指如注册中心类的单个具体组件,而是对 Dubbo 治理体系的抽象表达。控制面包含协调服务发现的注册中心、流量管…