《Windows Internals》10.1.20 Hive structure:为什么一个 Hive 在内部不是“键和值的平铺集合”,而是 block、base block、bin、cell 这种
个人主页杨利杰YJlio❄️个人专栏《Sysinternals实战教程》 《Windows PowerShell 实战》 《WINDOWS教程》 《IOS教程》《微信助手》 《锤子助手》 《Python》 《Kali Linux》《那些年未解决的Windows疑难杂症》让复杂的事情更简单让重复的工作自动化《Windows Internals》10.1.20 Hive structure为什么一个 Hive 在内部不是“键和值的平铺集合”而是 block、base block、bin、cell 这种分层结构《Windows Internals》10.1.20 Hive structure为什么一个 Hive 在内部不是“键和值的平铺集合”而是 block、base block、bin、cell 这种分层结构》1. 先说结论Hive 内部是“分层容器”不是“平面列表”2. 第一层Block——为什么 hive 先被切成 4 KB 的块2.1 为什么要先分 block3. 第二层Base block——为什么第一个 block 不是放键值而是放“全局元信息”3.1 这说明什么3.2 为什么 regf 特别值得记4. Hive 格式版本为什么重要1.5 和 1.6 不只是数字变化4.1 这说明什么4.2 为什么“全名 hash”这件事值得注意5. 第三层Cell——为什么真正的数据都落在 cell 里5.1 这意味着什么5.2 为什么要用 cell而不是直接用“键对象”和“值对象”平铺6. Table 10-6 最值得记的几类 cell为什么一个 key 后面其实藏着很多不同类型的 cell6.1 Key cellCM_KEY_NODE6.2 Value cellCM_KEY_VALUE6.3 Security cellCM_KEY_SECURITY6.4 Subkey-list cell / Value-list cell6.5 Big dataCM_BIG_DATA7. 第四层Bin——为什么 hive 扩容不是“多加一个 cell”而是“多分配一个 bin”7.1 为什么要有 bin 这一层7.2 Bin 和 block、cell 的关系怎么理解8. 为什么书里要专门说“空 bin、碎片、合并”因为 Hive 也会“碎片化”8.1 这说明什么8.2 为什么这很重要9. Cell index 是什么为什么说它才是 Hive 里“真正的连接线”9.1 这意味着什么9.2 一个典型例子10. 书里的例子为什么只用 Root、Sub Key、Val1、Val2因为它刚好把四层结构全讲透了11. 为什么搜索子键要排序而 value list 却不排序11.1 这说明什么子键为什么排序value 为什么不排序11.2 这对理解 Hive 有什么启发12. 从桌面支持和系统学习视角这一节到底有什么价值12.1 它能帮我彻底放弃“注册表就是树节点集合”的直觉12.2 它能帮我理解为什么 Hive 会碎片化、会重组、会整理12.3 它能帮我理解为什么某些注册表问题不是“键丢了”这么简单12.4 它能帮我把 Regedit、Hive 文件、Configuration Manager 三层打通13. 我的学习理解这一节真正教会我的是“注册表树是被拼出来的不是天然长出来的”14. 总结提升下一篇预告《Windows Internals》10.1.20 Hive structure为什么一个 Hive 在内部不是“键和值的平铺集合”而是 block、base block、bin、cell 这种分层结构》学到《Windows Internals》10.1.20 Hive structure这一节时我觉得这一小节特别关键因为它会把我们对注册表的理解再往下拽一层。前面我们已经知道注册表不是一个“大文件”而是一组hiveConfiguration Manager 会把这些 hive 组织成我们在 Regedit 里看到的整体逻辑结构。但是如果继续追问一句一个 hive 自己内部到底是怎么放数据的很多人的第一反应还是会很“朴素”不就是一堆 key 和 value 平铺着放吗最多再加点索引路径能找到就行了但书里讲得很清楚hive 内部不是简单平铺而是分成 block、base block、bin、cell 这些层级结构。Configuration Manager 先把 hive 逻辑上切成4 KB 的 block第一个 block 叫base block里面放全局元信息例如regf签名、序列号、时间戳、版本号、校验和、内部文件名等实际的注册表数据则以cell的形式组织而当 hive 扩展时系统会按更大的分配单元bin来增长。这一节最核心的一句话就是Hive 之所以不是“键和值平铺集合”是因为 Windows 要解决的不只是“能存”而是“如何扩展、如何定位、如何回收、如何校验、如何高效搜索”。1. 先说结论Hive 内部是“分层容器”不是“平面列表”如果只用一句话总结这一节我会这样说Hive 的内部组织更像“分层存储结构”而不是“把所有 key/value 顺序堆在一个大列表里”。书里先给出的核心框架是hive 会被逻辑地分成blocks第一个 block 是base block真正的数据组织在cells中hive 扩容时用的是bins不是直接一个 cell 一个 cell 随便往后接。这就意味着Windows 在设计 hive 时考虑的从来不是“只要能存进去就行”而是这些更底层的现实问题元信息放哪数据最小单元怎么定义扩容按什么粒度做空间碎片怎么处理键和值之间怎么链接搜索怎么优化也就是说Hive 不是“注册表树落到磁盘后的截图”而是一套专门为可扩展性和可管理性设计的数据结构。2. 第一层Block——为什么 hive 先被切成 4 KB 的块书里这一节一上来就讲得非常直接Configuration Manager 会把 hive 逻辑上分成 allocation units叫 blocks就像文件系统把磁盘分成 cluster 一样注册表 block 的大小固定为 4096 字节也就是 4 KB。Hive 扩展时也总是按 block 粒度增加。这句话特别重要因为它告诉我们hive 不是“一个连续无边界的大缓冲区”它从一开始就有基础分块概念而且这个分块粒度是固定的4 KB。2.1 为什么要先分 block这个设计特别像文件系统和内存管理的思路太细管理开销大太粗空间浪费多4 KB 是一个比较均衡的粒度而且这也有助于后面做校验扩容定位映射磁盘读写与内存组织之间的对齐所以 block 的意义不是“为了好看”而是给 hive 建立一个统一的最基础空间粒度。3. 第二层Base block——为什么第一个 block 不是放键值而是放“全局元信息”书里接着说hive 的第一个 block 叫 base block它里面保存的是 hive 的全局信息。书里列出的内容非常关键包括一个标识这是 hive 文件的签名regf两个更新序列号最近一次发起写操作的时间戳Winload 做过修复/恢复的信息hive 格式版本号校验和hive 内部记录的文件名例如\Device\HarddiskVolume1\WINDOWS\SYSTEM32\CONFIG\SAM。3.1 这说明什么说明 base block 本质上更像整个 hive 的“文件头 元数据头”。它不是为了直接存业务数据而是为了让 Configuration Manager 知道这是不是一个合法 hive它用什么格式最近写到了什么状态需不需要恢复该怎么验证它的完整性。3.2 为什么regf特别值得记因为这就像一个“魔数”或“签名”作用是让系统知道这份文件就是 hive不是别的普通二进制文件。很多底层结构文件都会有类似设计。在注册表这里regf就是那个最经典的识别标志。所以 base block 的存在本质上是告诉我们Hive 不是裸数据堆它首先是一种受严格格式约束的文件结构。4. Hive 格式版本为什么重要1.5 和 1.6 不只是数字变化书里在 base block 这一段还专门讲了 hive format versionConfiguration Manager 使用的 hive format version 是1.5它支持large values也就是大于 1 MB 的值同时它还改进了搜索方式不再只缓存名字前四个字符而是使用整个名字的 hash来减少冲突此外Configuration Manager 还支持differencing hives这类 hive 用的是1.6版本主要用于容器支持。4.1 这说明什么说明 hive 不是一成不变的“古老文件格式”它也是会进化的。而且这种进化不是表面变化而是直接体现在能支持更大 value能提高查找效率能支持更现代的场景比如容器。4.2 为什么“全名 hash”这件事值得注意因为这直接说明 Configuration Manager 很在乎查找性能。如果只缓存前四个字符名字相近时冲突会比较多。而改成全名 hash本质就是为了降低碰撞提高查找效率适应更复杂的注册表规模。也就是说Hive 结构不是静态存储设计它从一开始就兼顾了“未来要怎么更快查”。5. 第三层Cell——为什么真正的数据都落在 cell 里如果说 block 和 base block 更像“空间框架”和“文件头”那真正承载注册表内容的核心单位就是cell。书里明确说Windows 用 cell 作为 hive 内部的实际数据容器一个 cell 可以存keyvaluesecurity descriptorsubkey listkey value list每个 cell 数据起始处有一个四字节字符 tag用来标识其类型cell 头里还会记录 cell 的大小采用1’s complement的方式表示。5.1 这意味着什么意味着 Configuration Manager 眼中的 hive不是一串“树节点对象”而更接近一组类型不同的cell它们彼此引用、彼此关联最后共同拼出我们看到的树结构。5.2 为什么要用 cell而不是直接用“键对象”和“值对象”平铺因为 cell 这种设计更灵活不同类型都能统一放进一个基本框架里扩展和回收更容易同时还能和 bin/block 这套空间管理机制自然衔接所以这里最值得记住的一句话是注册表树在 hive 里不是“天然长出来的”而是由各种 cell 通过索引关系拼出来的。6. Table 10-6 最值得记的几类 cell为什么一个 key 后面其实藏着很多不同类型的 cell书里在 Table 10-6 里列出了多种 cell 类型。我们不用一次全背但有几类特别值得先建立印象。6.1 Key cellCM_KEY_NODE这是描述一个注册表 key 的 cell也叫key node。你可以把它理解成“这个 key 自己的主体信息” 存在这里但注意它通常并不把所有东西都自己包圆而是会引用父 key子 key 列表value 列表security cell 等。6.2 Value cellCM_KEY_VALUE这个就是注册表 value 本体的 cell。它描述某个值的名字、类型以及数据关联关系。6.3 Security cellCM_KEY_SECURITY这个用来承载安全描述相关内容。为什么要单独拆出来因为安全信息本身也可能被多个 key 复用拆开更利于管理。6.4 Subkey-list cell / Value-list cell这两类非常关键因为它们决定“树是怎么串起来的”。书里明确提到subkey-list cell里存的是子键 key cell 的 cell index 列表value-list cell里存的是该 key 的 value cell 列表。这就说明一个 key 的“子项结构”和“值结构”并不是直接塞在 key cell 里而是通过列表 cell 间接组织起来。这就是典型的“逻辑树物理拆分”设计。6.5 Big dataCM_BIG_DATA书里在这一小节前面提到 format 1.5 已支持大 value大于 1 MB。这类大数据在内部就不适合简单塞进普通 value cell会用到更专门的结构承载。所以如果你把 hive 想成“值都差不多”那就会低估它内部结构复杂度。7. 第四层Bin——为什么 hive 扩容不是“多加一个 cell”而是“多分配一个 bin”这一点特别关键因为它直接解释了为什么书名里不是只提 block 和 cell还专门提bin。书里明确说当一个 cell 要加入 hive而现有空间不够时系统就会创建一个新的allocation unit叫binbin 也有自己的头头里有签名hbin还记录了这个 bin 在 hive 文件中的 offset 和大小。7.1 为什么要有 bin 这一层因为如果直接按 cell 频繁扩容会让管理开销太碎。书里甚至直接说用 bin 而不是直接按 cell 跟踪活跃部分可以减少一些管理负担系统分配/释放 bin 的频率通常远低于 cell这会让 Configuration Manager 更高效地管理内存。换句话说bin 是为了让 hive 的增长和空间回收不至于过碎。7.2 Bin 和 block、cell 的关系怎么理解我自己更喜欢这样记block最基础的固定粒度4 KBbin更大的分配容器可以包含一个或多个 blockcell真正装 key/value/安全/列表等数据的最小逻辑单元。也就是说HiveBase block多个 binbin 由一个或多个 4KB block 构成bin 内包含多个 cellkey cellvalue cellsecurity cellsubkey-list / value-list cell这张图背后的核心意思就是Hive 内部不是“平铺一堆节点”而是“容器里再套容器最后才落到数据单元”。8. 为什么书里要专门说“空 bin、碎片、合并”因为 Hive 也会“碎片化”这部分特别有意思因为它让 hive 看起来越来越像文件系统了。书里说当系统在 hive 里不断新增和删除 cell 时可能会形成空 bin和被打碎的空闲区域这和磁盘上反复创建/删除文件导致的碎片化很像当一个 bin 变空时Configuration Manager 会尽量把相邻空 bin 合并成更大的连续空 bin相邻的已删除 cell 也会被合并成更大的 free cell只有当 hive 尾部的 bin 变空时Configuration Manager 才会真正缩小 hive此外系统在 hive 初始化阶段还会跑Reorganization algorithm来整理。8.1 这说明什么说明 hive 不是永远完美紧凑永远新增删除都不留痕相反它也会出现类似内部碎片空间不连续尾部无法回收需要重组整理这种非常“存储系统化”的问题。8.2 为什么这很重要因为它再次证明Hive 不是“键和值字典”那么简单它本质上已经很接近一个小型专用存储系统。这也是为什么后面书里还要讲cell mapshive reorganizationincremental loggingreliability / recovery这些都不是“普通配置文件”该有的复杂度。9. Cell index 是什么为什么说它才是 Hive 里“真正的连接线”这一段非常值得认真看因为它直接解释了 hive 的“树”到底怎么被拼起来。书里说得很清楚创建 hive 结构连接关系的是cell indexes一个 cell index 的定义是cell 在 hive 文件中的 offset - base block 的大小所以 cell index 本质上像一个从一个 cell 指向另一个 cell 的指针Configuration Manager 会把它解释成“相对于 hive 起点的偏移”。9.1 这意味着什么意味着 hive 内部的层级结构并不是靠直接嵌套对象而是靠cell index 引用关系拼起来的。9.2 一个典型例子书里举得很具体key cell 里会有父 key 的 cell index也会有 subkey-list cell 的 cell indexsubkey-list cell 里再列出每个子 key cell 的 cell indexes然后系统再逐个检查子 key 名字看有没有匹配目标。这说明树不是“实体嵌套”而是“索引网络”。换句话说注册表树在 hive 里更像“靠偏移量引用拼出来的图结构”而不是 UI 里那种天然嵌套树。10. 书里的例子为什么只用 Root、Sub Key、Val1、Val2因为它刚好把四层结构全讲透了书里举了一个特别经典的简单示意例子sample hive 包含一个base block和两个bin第一个 bin 是空的第二个 bin 里包含多个cell从逻辑上看整个 hive 只有两个 keyRootSub KeyRoot下面还有两个 valueVal1Val2subkey-list cell用来定位Root的子键value-list cell用来定位Root的值第二个 bin 里的空白区域其实是empty cells。这个例子非常好因为它一口气把四个概念串起来了base block放全局头信息bin放实际数据容器cell存 key/value/list/security 等单元cell index把这些单元连成逻辑树。也就是说书里这个例子并不是为了简化而简化而是为了让你一下子看懂逻辑树只是表象真正的内部实现其实是一组带索引关系的 cell 结构。11. 为什么搜索子键要排序而 value list 却不排序这一点特别能体现 Configuration Manager 的取舍思路。书里明确说为了优化 subkey 搜索Configuration Manager 会把subkey-list cells 按字母顺序排序这样查找子键时就可以做binary search二分查找但value-list cells 不排序新的 value 总是加到列表尾部。11.1 这说明什么说明 Windows 并没有“处处都追求绝对一致结构”而是按使用场景做了不同优化。子键为什么排序因为查找子键非常频繁排序后可以二分查找明显更快。value 为什么不排序因为 value 的访问模式和子键不同而且追加到末尾能减少维护排序的成本。11.2 这对理解 Hive 有什么启发这说明 hive 内部结构不是“理想化教科书设计”而是一套围绕实际访问模式、空间管理成本和性能权衡做出来的工程设计。所以 Hive 不是“纯粹追求结构优雅”而是“在查找速度、写入成本、空间管理之间做平衡”。12. 从桌面支持和系统学习视角这一节到底有什么价值很多人会觉得 Hive structure 太底层但我觉得它很有价值。12.1 它能帮我彻底放弃“注册表就是树节点集合”的直觉这一步非常重要。因为后面你再学symbolic linkscell mapsvirtualizationfilteringreliabilityrecovery都会用到这个更底层的理解。12.2 它能帮我理解为什么 Hive 会碎片化、会重组、会整理如果你不知道hive 用 bin 管扩容用 cell 放数据空闲 cell / 空 bin 会累积那你很难真正理解为什么后面会有hive reorganization。12.3 它能帮我理解为什么某些注册表问题不是“键丢了”这么简单因为底层还涉及cell 索引关系安全 cellvalue-list / subkey-listbase block 元信息bin 结构完整性所以有些损坏不是“少一个值”而是结构层出了问题。12.4 它能帮我把 Regedit、Hive 文件、Configuration Manager 三层打通也就是Regedit看到逻辑树Hive 文件看到 block/bin/cellConfiguration Manager负责解释和组织它们这三层一旦打通你的理解就会一下子立体很多。13. 我的学习理解这一节真正教会我的是“注册表树是被拼出来的不是天然长出来的”我觉得10.1.20 Hive structure最厉害的地方不是多教了几个术语而是让我真正理解注册表树并不是 hive 文件天然自带的“长相”它是通过 block、base block、bin、cell、cell index 这套机制一点点拼出来的。以前如果只看 Regedit很容易觉得这个 key 在这里下面就是它的子键右边就是它的值一切都很自然但这一节告诉我这个 key 其实是某个 cell它的子键列表在别的 cell 里它的值列表在另外的 cell 里它和父节点的关系靠 cell index它所在 bin 还可能夹杂空 cell、碎片和安全 cell。这一下注册表就不再是“静态树形配置表”了而更像一个专门为注册表场景设计的小型分层存储引擎。14. 总结提升如果让我用一句话总结《Windows Internals》10.1.20 Hive structure我会这样说Hive 在内部不是“键和值的平铺集合”而是一套分层组织的数据结构4 KB 的 block 构成基本空间粒度第一个 block 是保存全局元信息的 base block实际数据放在 cell 中而 hive 的增长与空间管理则依赖更大的分配单元 bin最终Configuration Manager 再通过 cell index 把这些分散单元拼接成我们看到的注册表树。这篇最值得记住的 10 个结论是Configuration Manager 会把 hive 逻辑地切分成 4 KB 的 block。第一个 block 叫 base block里面有regf签名、序列号、时间戳、版本号、校验和、内部文件名等全局元信息。Hive format 1.5 支持大于 1 MB 的 value并改进了名称查找1.6 用于 differencing hives。真正的数据存放在 cell 里cell 可以表示 key、value、安全描述符、subkey 列表、value 列表等。cell 头里会记录大小cell 还有类型 tag。当 hive 扩容时系统按更大的分配单元 bin 来增长而不是直接一条条加 cell。bin 有自己的hbin头还记录 offset 和 size。hive 的树形关系是通过 cell index 串起来的cell index 本质上是相对 hive 起点的偏移引用。subkey-list cells 会按字母排序方便二分查找value-list cells 不排序新值直接加在末尾。Hive 也会碎片化Configuration Manager 会合并空 bin、合并空闲 cell并在初始化阶段做 reorganization。我觉得这一节最值得沉淀成一句自己的话就是Regedit 给我们看的是“树”但 Hive 真正落盘的方式更像“带头部、分块、分配单元、索引引用和空间整理能力的专用存储结构”。下一篇预告《Windows Internals》10.1.21 Cell maps为什么在现代 Windows 里cell index 已经不能再简单理解成“base offset”而要靠两级映射表去找真实内存位置》这一篇可以继续把cell index 为什么是“文件偏移”Winload 早期为什么能直接base offset为什么 hive 一长大、视图一变碎就必须引入 cell map1024 × 512 的两级映射目录“像页表一样找 cell”到底是什么意思全部串起来。返回顶部