《Windows Internals》10.1.18 Startup and the registry process:为什么现代 Windows 不再把所有 Hive 都简单塞进 paged poo

张开发
2026/5/17 10:43:39 15 分钟阅读
《Windows Internals》10.1.18 Startup and the registry process:为什么现代 Windows 不再把所有 Hive 都简单塞进 paged poo
个人主页杨利杰YJlio❄️个人专栏《Sysinternals实战教程》 《Windows PowerShell 实战》 《WINDOWS教程》 《IOS教程》《微信助手》 《锤子助手》 《Python》 《Kali Linux》《那些年未解决的Windows疑难杂症》让复杂的事情更简单让重复的工作自动化《Windows Internals》10.1.18 Startup and the registry process为什么现代 Windows 不再把所有 Hive 都简单塞进 paged pool而是专门引入了 Registry 进程《Windows Internals》10.1.18 Startup and the registry process为什么现代 Windows 不再把所有 Hive 都简单塞进 paged pool而是专门引入了 Registry 进程1. 先说结论Registry 进程的出现本质上是“注册表内存模型升级”2. 旧时代的做法为什么说 Windows 8.1 之前的模式已经不太扛得住了2.1 为什么 paged pool 模式会越来越吃力第一注册表越来越像“大对象”第二内核池资源压力会更现实3. 为什么 SYSTEM Hive 和 SOFTWARE Hive 在启动中的命运不一样3.1 SYSTEM / ELAM3.2 SOFTWARE4. Registry process 是什么时候创建的它到底是什么4.1 这说明什么4.2 为什么叫 minimal process5. 真正的关键变化什么叫 section-backed registry5.1 这句话怎么通俗理解5.2 为什么是 2 MB views6. 为什么说这种新模式更省内存关键在 working set 和 commit charge 的区别6.1 这句话怎么通俗理解旧模式新模式6.2 为什么这很重要7. 为什么书里要特别提“64 MB hard working set limit”7.1 这意味着什么7.2 这为什么很有意义8. 应用或系统访问注册表时为什么还要“attach 到 Registry process”8.1 为什么这一步是合理的8.2 那是不是每次都要切换地址空间9. Registry process 主要拿来干什么一句话低层 Hive 文件 I/O10. 写入时又是怎么处理的为什么这里又引出了 copy-on-write 和日志10.1 这说明什么10.2 这样做的好处是什么第一写路径更灵活第二恢复能力更强11. Reconciler 是什么为什么它默认一小时才跑一次11.1 为什么不是每次改完立刻全量写回11.2 这对理解注册表很重要吗12. 从桌面支持和运维视角这一节真正有什么现实价值12.1 它帮我理解为什么现代 Windows 的注册表性能模型变了12.2 它帮我理解为什么大型 SOFTWARE hive 不再必然是灾难12.3 它帮我理解 KCB 缓存为什么这么重要12.4 它帮我理解为什么注册表访问不是总会造成“很重的上下文切换”12.5 它帮我理解 %SystemRoot%\System32\Config 之外的“运行时层”也很重要13. 这一节最容易被误解的 6 个点我帮你一次理顺13.1 误区一Registry process 就是“又一个普通系统进程”13.2 误区二现代 Windows 把所有 hive 都搬进了 Registry process13.3 误区三section-backed registry 就是“文件映射版 Regedit”13.4 误区四每次访问注册表都一定会切换到 Registry process13.5 误区五写入视图就等于主 hive 文件已经同步改好了13.6 误区六64 MB 是注册表的总大小限制14. 我的学习理解这节真正讲的不是“多了个进程”而是“注册表从静态数据走向运行时系统”15. 总结提升下一篇预告《Windows Internals》10.1.18 Startup and the registry process为什么现代 Windows 不再把所有 Hive 都简单塞进 paged pool而是专门引入了 Registry 进程前面几篇我们已经把Hive、Hive size limits、Configuration Manager、Registry internals这些基础打得差不多了。到了10.1.18 Startup and the registry processWindows 又往前走了一步它不再满足于“把 hive 读进来就算完事”而是开始思考一个更现实的问题如果注册表 Hive 越来越大尤其是SOFTWARE这种可能达到几百 MB 的 Hive还一直简单放在 paged pool 里系统到底还能承受多久书里给出的答案非常清楚在 Windows 8.1 之前NT 内核把每个已加载 hive 的内容都放在 paged pool 里而且大多数 hive 一直留到关机典型例子就是SOFTWAREhive它由 Session Manager 在系统启动 phase 1 后加载而且有时会达到数百 MB。到了 Windows 10 RS4微软引入了 section-backed registry 和专门的 Registry process开始把 hive 的映射、I/O 和内存占用管理做得更精细。所以这篇文章我就把10.1.18 Startup and the registry process这一节彻底讲透。这一节最核心的一句话就是现代 Windows 引入 Registry 进程不是为了“多搞一个系统进程”而是为了把大体量 Hive 的映射、访问和 I/O 从粗放式 paged pool 模式升级成更可控、更省内存、更适合大规模注册表场景的模型。1. 先说结论Registry 进程的出现本质上是“注册表内存模型升级”如果只用一句话总结这一节我会这样说Registry process 本质上是 Windows 为大型 hive 尤其是SOFTWAREhive 引入的一种更高效、更可控的运行时承载方式。为什么这么说因为书里先讲了旧模式的问题再讲了新模式的设计旧模式所有已加载 hive 内容都进 paged pool新模式把 hive 文件做成 section-backed mapping映射到一个专门的 Registry process 地址空间里。也就是说这不是一个“小优化”而是从“把 hive 内容当作普通内核池内存数据”转向“把 hive 当作文件支撑的映射对象来管理”。2. 旧时代的做法为什么说 Windows 8.1 之前的模式已经不太扛得住了书里讲得很直接Before Windows 8.1, the NT kernel was using paged pool for storing the content of every loaded hive file. Most of the hives loaded in the system remained in memory until the system shutdown.这句话翻成更通俗的话就是hive 一旦加载内容就被放进 paged pool而且大多数会长期留在内存里不是加载一下就很快释放。书里还专门举了一个特别有代表性的例子SOFTWAREhive 是Session Manager 在 phase 1 完成后加载它有时候可能达到multiple hundreds of megabytes。这说明什么当 hive 体积越来越大时继续把它们整体塞进 paged pool本身就会成为系统内存压力源。2.1 为什么 paged pool 模式会越来越吃力原因其实很好理解。paged pool 虽然可以分页但它毕竟还是一种内核侧池内存资源系统级共享资源需要被整个系统其他核心组件一起争用的空间如果大型 hive 长期占据这里就会带来两个现实问题第一注册表越来越像“大对象”尤其是SOFTWARE这种 hive可能已经不是“小配置仓库”而是很大的系统级配置集合。第二内核池资源压力会更现实注册表不是系统唯一需要内存的组件。如果 hive 内容始终以这种方式常驻随着系统功能和软件生态越来越复杂代价会越来越明显。所以微软最终必须换一种思路。3. 为什么 SYSTEM Hive 和 SOFTWARE Hive 在启动中的命运不一样这一点特别值得单独讲因为它正好把前一篇和这一篇串起来了。前一篇 10.1.17 我们已经说过HKLM\SYSTEMhive 在启动很早期就要被 Winload 整体读入物理内存因为当时虚拟内存分页还没有启用。而这篇 10.1.18 又进一步告诉我们在phase 1 的 NT kernel initializationConfiguration Manager 会初始化注册表相关组件并创建Registry process预加载的 hiveSYSTEM 和 ELAM继续驻留在 nonpaged memory 中后面才是 Session Manager 去加载SOFTWAREhive。这意味着3.1 SYSTEM / ELAM更早参与启动更靠近引导阶段继续驻留在 nonpaged memory不走后面SOFTWARE那套 section-backed 映射路径。3.2 SOFTWARE启动更晚才加载更适合用新的文件映射模型承载也正因此成为 Registry process 机制的核心对象之一。所以 Registry process 不是“所有 hive 一刀切重构”而是重点解决那些大体量、运行期长期存在的 hive尤其是 SOFTWARE。4. Registry process 是什么时候创建的它到底是什么书里对这个时间点和身份描述得很明确在NT kernel initialization 的 phase 1Configuration Manager 启动时会初始化cacheworker threadstransactionscallbacks support 等组件然后在加载所需 hive 之前创建 Registry process。而这个 Registry process 的身份也很有意思它是一个fully-protectedminimal process保护级别和 SYSTEM process 一样都是WinSystem levelConfiguration Manager 用它来执行大多数已打开 hive 的 I/O。4.1 这说明什么说明 Registry process 不是那种“给用户看、给任务管理器看的业务进程”而是专门为了注册表运行时承载和 hive I/O 而设计的系统内部进程。它的定位非常纯粹不是 UI 进程不是服务宿主不是通用容器而是注册表在现代 Windows 中的一块专属“运行空间”。4.2 为什么叫 minimal process因为它不是为了跑一堆用户逻辑而是为了给 Configuration Manager 提供一个合适的地址空间和 I/O 承载位置。这就决定了它“存在感很低”但作用非常关键。Registry process 的价值不在“多做事”而在“把注册表相关的大块内存映射和底层 I/O 从传统内核池模型里拆出来”。5. 真正的关键变化什么叫 section-backed registry这一节的灵魂其实就是这四个词section-backed registry书里在讲SOFTWAREhive 时写得很明确系统会为SOFTWAREhive 文件创建一个section objectConfiguration Manager 把这个文件按2 MB chunks切开然后在 Registry process 的用户态地址空间里为每个 chunk 创建reserved mapping调用的是NtMapViewOfSection这些 reserved mapping 由有效的 VAD 跟踪但此时并不分配实际页面每个 2 MB 视图最开始都是read-only。5.1 这句话怎么通俗理解你可以把它理解成Windows 不再一上来就把整个 SOFTWARE hive 的内容粗暴搬进 paged pool而是先给它在 Registry process 里“预留地址空间窗口”真正访问到哪一块再由内存管理器按需把页面带进来。这就是“section-backed”的核心思路不是先把所有内容都变成内核池数据而是让 hive 文件自己成为页面来源通过 section/view 机制按需映射。5.2 为什么是 2 MB views书里明确说了SOFTWAREhive 文件会被切成2 MB chunks。这个粒度意味着管理足够粗不会细碎到太难维护又足够细不至于为了用很少一点数据就把特别大的整块都拖进内存这其实是一种折中设计。也就是说现代注册表对大 hive 的处理方式已经很像“文件映射 分块按需载入”而不是“整体常驻”。6. 为什么说这种新模式更省内存关键在 working set 和 commit charge 的区别这里是这节最容易“看过去但没吃透”的地方。书里明确说当 Configuration Manager 想读取某些 hive 数据时它访问对应视图的页面会产生access fault然后由内存管理器把共享页带进内存这时增加的是working set charge而不是 commit charge因为这些页面是由 hive 文件本身支撑的不是页文件。6.1 这句话怎么通俗理解你可以这样理解旧模式更像“先把整本书搬进办公室再开始翻”。新模式更像“书放在档案库里你先留好书架位置需要翻哪几页再把那几页拿进来”。而且这些页是文件本身支撑的不是额外靠页文件承诺出来的内存。6.2 为什么这很重要因为这意味着对大型 hive 而言内存占用从“先整体压上来”变成了“按需映射、按需进入 working set”。这就是 Registry process 模式最核心的节省点之一。7. 为什么书里要特别提“64 MB hard working set limit”这个数字非常重要因为它直接体现了微软想把注册表的内存行为“钉住”。书里明确写到在初始化时Configuration Manager 会给 Registry process 设置64 MB 的 hard working set limit这意味着在高内存压力场景下可以保证注册表最多只消耗64 MB working set。7.1 这意味着什么意味着微软不是只做了“映射优化”还进一步做了工作集上限控制也就是说不是让注册表无限按需长大而是即使在压力场景下也要有一个明确的内存上边界。7.2 这为什么很有意义因为这和前一篇 Hive size limits 一样都体现了 Windows 一种很鲜明的工程风格不只是让东西“能工作”还要让它的资源消耗可预测、可约束、可管理Registry process 的引入本质上是把注册表从“能跑”推进到了“能控”。8. 应用或系统访问注册表时为什么还要“attach 到 Registry process”这也是这一节特别有内部味道的地方。书里写得很清楚每当应用程序或系统通过 API 访问注册表Configuration Manager 会attach 到 Registry process 的地址空间做完需要的工作后再返回结果。这说明什么说明 hive 映射的关键视图不在“调用者自己进程里”而在 Registry process 这个专门的地址空间里。所以访问时需要临时切过去操作。8.1 为什么这一步是合理的因为这样可以把hive 文件映射大块 section 视图相关低层 I/O尽量收拢在 Registry process 里统一承载而不是散在各种调用者上下文里。这正是“专门引入 Registry process”这件事的意义所在。8.2 那是不是每次都要切换地址空间书里马上补了一个特别关键的优化点并不总需要如果应用访问的 key 已经在缓存里也就是Key control blockKCB已经存在那么 Configuration Manager 可以跳过 process attach直接返回缓存数据。所以 Registry process 不是“每次访问都很重”它和 KCB 缓存优化是配套存在的。9. Registry process 主要拿来干什么一句话低层 Hive 文件 I/O书里用了一个非常直接的表述The registry process is primarily used for doing I/O on the low-level hive file.这句话特别值得记住因为它把这个进程的核心定位讲透了不是给用户直接用不是为了一堆业务逻辑也不是为了替代所有注册表内部对象它的重点是低层 hive 文件 I/O 承载。所以你可以这样理解Configuration Manager 负责逻辑KCB 负责缓存Registry process 负责让大 hive 文件的映射和 I/O 有一个更合适的运行空间。这三者加在一起才是现代注册表运行模型。10. 写入时又是怎么处理的为什么这里又引出了 copy-on-write 和日志如果只讲读取这一节还不算完整。写入时的设计也很精彩。书里说得很清楚当系统修改 hive 中的 key 或 value 时会先把 2 MB 视图的内存保护改成PAGE_WRITECOPY也就是执行copy-on-write对这类页面写入会产生新的 private pages并增加system commit charge同时注册表更新请求到来时系统会立刻把新条目写进 hive 的 log但主 hive 文件对应的页面写回会被延后。10.1 这说明什么说明现代注册表模型并不是改了值立刻同步去重写主 hive 文件而是更像先在映射视图里写先记日志主文件写回延后。10.2 这样做的好处是什么好处有两个很明显第一写路径更灵活先日志、后主文件可以降低同步重写主文件的频率。第二恢复能力更强因为日志先落下来了后续就有恢复基础。这也正好和后面的Incremental logging、Reconciler章节自然衔接。11. Reconciler 是什么为什么它默认一小时才跑一次书里对这个后台线程的描述很有意思dirty hive pages 像普通内存页一样可以被换出到磁盘真正写回 primary hive file 的时机hive 被卸载时或者由Reconciler执行Reconciler 是 Configuration Manager 的一个lazy writer thread默认每小时执行一次周期还可以通过HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Configuration Manager\RegistryLazyReconcileInterval调整。11.1 为什么不是每次改完立刻全量写回因为那样开销太大。尤其在大型 hive 和高频修改场景下频繁同步主文件会带来明显性能代价。所以 Windows 的思路是先记日志主文件晚一点慢慢 reconcile。这就是 lazy writer 的味道。11.2 这对理解注册表很重要吗非常重要。因为它说明现代注册表并不是“修改 主文件立即改完”的朴素模型而是“视图、日志、延迟落盘”三者协同的模型。这和很多人对注册表“像 ini 文件那样即写即改”的直觉完全不同。12. 从桌面支持和运维视角这一节真正有什么现实价值很多人看到 Registry process 会觉得太底层。但我觉得它至少有 5 个现实价值。12.1 它帮我理解为什么现代 Windows 的注册表性能模型变了以前粗糙理解是hive 常驻数据现在更准确的理解是hive 文件支撑的映射对象访问 attach cache on-demand page-in写入 copy-on-write log lazy reconcile。12.2 它帮我理解为什么大型 SOFTWARE hive 不再必然是灾难前提当然不是“无限大都没事”但至少现代 Windows 已经不再是简单把所有 loaded hive 内容都长期堆进 paged pool。12.3 它帮我理解 KCB 缓存为什么这么重要书里明确说如果 key 已经在缓存中Configuration Manager 可以跳过 attach直接返回缓存数据。这说明 KCB 不是附属小技巧而是现代注册表性能模型里的关键优化点。12.4 它帮我理解为什么注册表访问不是总会造成“很重的上下文切换”因为有时确实会 attach 到 Registry process但缓存命中时可以跳过。所以不能一概而论说“每次访问注册表都很重”。12.5 它帮我理解%SystemRoot%\System32\Config之外的“运行时层”也很重要前面我们理解了 hive 文件本身而这一节又提醒我们文件只是静态载体真正的运行时行为还要看 Registry process、映射视图、日志和 Reconciler。13. 这一节最容易被误解的 6 个点我帮你一次理顺13.1 误区一Registry process 就是“又一个普通系统进程”不对。它是 fully-protected、minimal process核心作用是承载 hive 的低层 I/O 和映射。13.2 误区二现代 Windows 把所有 hive 都搬进了 Registry process也不对。书里明确说预加载的SYSTEM和ELAMhive 仍驻留在 nonpaged memory 中。13.3 误区三section-backed registry 就是“文件映射版 Regedit”不准确。它是 Configuration Manager 面向 hive 文件运行时承载方式的升级而不是 UI 功能变化。13.4 误区四每次访问注册表都一定会切换到 Registry process不对。KCB 已命中时Configuration Manager 可以跳过 attach。13.5 误区五写入视图就等于主 hive 文件已经同步改好了不对。写入会先走 copy-on-write 和日志主 hive 文件写回是延后的。13.6 误区六64 MB 是注册表的总大小限制不是。它是 Registry process 的 hard working set limit用于高内存压力场景下控制注册表的 working set 消耗。14. 我的学习理解这节真正讲的不是“多了个进程”而是“注册表从静态数据走向运行时系统”我觉得10.1.18 Startup and the registry process最厉害的地方不是让我记住Registry process2 MB views64 MB working setReconciler这些关键词本身而是它让我真正意识到注册表不是“文件 API”这么简单它在现代 Windows 里已经是一套完整的运行时系统。这套运行时系统里有启动阶段的预加载 hive运行期的大 hive 映射专门地址空间承载KCB 缓存copy-on-write 写入延迟写回日志与 reconcile。这就意味着我们以后看注册表不能只停在“值在哪”“文件在哪”而要进一步看到它是怎么被映射、怎么被访问、怎么被缓存、怎么被写回的。而 Registry process恰恰就是这一层的核心代表。15. 总结提升如果让我用一句话总结《Windows Internals》10.1.18 Startup and the registry process我会这样说现代 Windows 不再把所有已加载 hive 的内容简单堆在 paged pool 里而是通过 section-backed registry 和专门的 Registry process把大型 hive 尤其是SOFTWAREhive 的映射、I/O、working set 和写回行为做成了一套更高效、更可控、更适合大规模注册表场景的运行时模型。这篇最值得记住的 8 个结论是在 Windows 8.1 之前已加载 hive 的内容主要放在 paged pool 中而且很多会一直驻留到关机。SOFTWAREhive 是典型的大 hive它在 Session Manager 完成 phase 1 启动后加载有时可达数百 MB。在 NT kernel initialization phase 1Configuration Manager 会创建 Registry process。Registry process 是 fully-protected、minimal process主要用于已打开 hive 的低层 I/O。预加载的SYSTEM和ELAMhive 继续驻留在 nonpaged memory而SOFTWAREhive 会通过 section object 2 MB views 映射到 Registry process。按需访问视图页面时增加的是 working set charge而不是 commit charge因为页面由 hive 文件本身支撑。Registry process 的 hard working set limit 在初始化时被设为 64 MB用于高压力场景下控制注册表 working set 占用。注册表写入采用 copy-on-write日志先写主 hive 文件延后由 Reconciler 等机制回写。我觉得这一节真正建立起来的是这样一个更成熟的理解现代 Windows 注册表已经不是“加载文件然后常驻内存”那么简单而是一套围绕映射、缓存、工作集、日志和延迟写回建立起来的运行时系统。下一篇预告《Windows Internals》10.1.19 Registry symbolic links为什么有些注册表键看起来像真的在那儿其实只是被配置管理器“重定向”到了别处》这一篇可以继续把REG_LINKSymbolicLinkValueHKLM\SAM为什么本质上是符号链接为什么 Regedit 看不到这个值“路径看起来一样”与“真实来源不一样”之间的关系全部串起来。返回顶部

更多文章