Hive 注册表那点事( 5.0 VS 6.0 )

现象

       5.0 移置到 6.0 上的时候,发现 Hive-Registry 无效,具体的现象是在控制面板中屏幕校准后 Cold Boot 机器校准数据丢失。

       环境变量 PRJ_ENABLE_REGFLUSH_THREAD 和 PRJ_ENABLE_FSREGHIVE 配置为 1 ,同时注册表项 "RegistryFlags 配置为 0 。

分析

      首先温习一下 Hive 注册表信息更新的相关基本知识

通过配置注册表 HKEY_LOCAL_MACHINE/init/BootVars 下的注册项 "RegistryFlags 来配置 Hive 注册表的数据更新方法。

注册项 "RegistryFlags 可能的值及其含义如下:

Dword value

Description

none or 0

Default setting. Flushes the registry nondeterministically

1

Enables aggressive flushing

2

Disables background flushing

       详细解释如下:

       当配置为 1 的情况下,将使用 Aggressive Flush 的方式来更新 Hive 数据,也就是 Flush On Close ,即在每次调用 RegCloseKey 的时候会更新一次注册表,显然比较浪费系统资源。

       当配置为 0 的情况下,使用 Lazy Flush 方式更新注册表,这个也是系统默认的情况。在这种配置情况下,如果依然想保存 Hive 注册表中的更改项的话,有两种如下两种选择:

>> 系统关机前调用 API RegFlushKey 将修改的注册表项写入到存储设备上,如果保存成功将返回成功的标记。

>> 配置环境变量 PRJ_ENABLE_REGFLUSH_THREAD 来创建 Flush 进程来定期更新 Hive 注册表的改动项。

       创建的 Flush 线程的优先级

[HKEY_LOCAL_MACHINE/System/ObjectStore/RegFlush
; To monitor the flushing from an external process add "ActivityName
; The activity name is a global named event that filesystem
;    "ActivityName
; Create an thread in filesys
SpawnThread
; Make the thread IDLE priority
dword:FF
; ActivityThreshold specifies the # of reg
ActivityThreshold
; Timeout period in ms for a flush (flush occurs if there have been some changes during this period).
FlushPeriod

       系统会按照 SpawnThread 新建一个优先级为 FlushPriority256 的线程,按照 FlushPeriod 周期性地去检查注册表的变化并加以保存。

      本案的分析

本文要重点说明的就是这个地方, 5.0 中和 6.0 中 "FlushPeriod 的默认值是不一样的, 5.0 中默认值为 0x3E8 即 1000ms ,而 6.0 中为 0x1D4C0 ,即 120000ms 。这个地方的差异就造成了在 6.0 系统下注册表的修改值不能够及时的进行保存。

针对 120000ms 的情况,也就是说,当你修改了注册表后,修改的注册表值将会在大约 120000ms 后才刷新到存储设备上,这也造成了在 6.0 上 Hive 注册表不能够保存的问题。

解决方法

为了在 6.0 能够及时的保存注册表信息,需要将默认的 "FlushPeriod 的值改为比较小的值,可以在 Platform.reg 中添加如下的值来覆盖系统的默认值:

[HKEY_LOCAL_MACHINE/System/ObjectStore/RegFlush
; Timeout period in ms for a flush (flush occurs if there have been some changes during this period).
FlushPeriod

       其实 6.0 上支持 Hive-Registry ,还需要比 5.0 上多配置一个环境变量即 PRJ_ENABLE_FSREGHIVE ,这个也应该时 6.0 的一个 Bug 。    

附带说一句, Windows Mobile6.5 上也存在类似的问题,在此不再赘述。