引言:
Windows CE作为一种嵌入式的操作系统,已经有了10多年的历史,从早的1.0版本到如今的的6.0版本。Windows CE已经在嵌入式操作系统领域占据了非常重要的地位,同时还派生出了很多不同的版本,应用到不同的领域,Windows Mobilej就是其中非常成功的一个版本。
作为一种嵌入式操作系统,我们有必要了解它的启动过程和加载机制,特别是其中的注册表加载是系统加载的。Windows CE内核创建过程用的REG文件几乎和其他桌面版本Windows操作系统就有相同的格式,只是去掉了文件顶部的版本标记,防止开发者错误的将Windows CE的注册表信息添加到主机的注册表系统里,造成系统的故障。
1、 Windows CE注册表简介:
与其他桌面版本Windows一样,Windows CE也使用注册表(Registry)来保存应用程序、驱动程序和用户的设定以及其他一些配置信息。 Windows CE注册表也采用树形结构来管理配置信息。
Windows CE支持四个根键,描述如下:
键名描述
HKEY_LOCAL_MACHINE 硬件和驱动配置数据
HKEY_CURRENT_USER 用户配置数据
HKEY_CLASSES_ROOT OLE 文件类型匹配配置数据
HKEY_USERS 适用于所有用户的数据
由于嵌入式系统的特点,一些嵌入式设备是没有外存的。因此Windows CE的注册表提供了两种实现方式:基于RAM的注册表(RAM-Based Registry)和基于Hive的注册表(Hive-Based Registry)。我们可以选择在Windows CE中使用任何一种注册表,注册表类型对于用户和应用程序来说是透明的。
2、 Windows CE注册表的类型和加载过程
由于嵌入式系统的特点,一些嵌入式设备是没有外部存存储设备。因此Windows CE的注册表提供了两种实现方式:基于RAM的注册表(RAM- Based Registry)和基于Hive的注册表(Hive-Based Registry)。我们可以选择在Windows CE中使用任何一种注册表,通常在我们的ARM嵌入式系统中会选择Flash作为外部存储设备,所以我们选择基于Hive的注册表类型。下面我们分析一下Windows CE注册表的加载过程:
如图
nk.exe执行,启动filesys.exe。
filesys.exe加载引导HIVE,此时引导HIVE位于nk.bin解压之后的文件中。
filesys.exe启动device.exe,之后处于等待状态,等待device.exe将包含系统HIVE的文件系统和存储设备的驱动程序加载完毕。而这个文件系统和存储设备的驱动程序存在于引导HIVE中。device.exe加载上述所说的文件系统驱动程序和存储设备驱动程序,使之开始工作。之后device.exe处于等待状态。filesys.exe被唤醒,加载并且安装系统HIVE。之后filesys.exe处于等待状态。nk.exe按照系统HIVE的信息开始执行初始化工作。其中包括加载驱动程序和启动一些应用程序。其中加载驱动程序一般由device.exe执行,而启动应用程序由filesys.exe执行。这时device.exe和filesys.exe已经被唤醒。
3 基于RAM的注册表
正如其名,基于RAM的注册表把整个注册表作为一个对象存储堆存放在系统的内存中。这意味着如果对系统进行冷启动或者系统断电,对注册表的所有改动都会丢失。
如果使用基于RAM的注册表,对注册表的读写访问操作会变得非常高效。因此基于RAM的注册表比较适用于没有外部存储,而且有电池保存内存数据(battery-backed RAM)的设备。如果有外存且经常冷启动的设备采用基于RAM的注册表,则需要在系统断电的时候对注册表进行保存,等系统再次启动时对保存的注册表进行还原。
Windows CE提供了两种方法用来断电保存基于RAM的注册表:
1. Windows CE提供了两个系统API用来保存和还原整个注册表,它们的原形如下:
BOOL RegCopyFile(
LPCWSTR lpszFile // 保存注册表信息的文件的名字
);
BOOL RegRestoreFile(
LPCWSTR lpszFile // 保存注册表信息的文件的名字
);
如果要保存和恢复注册表,我们只需要在系统断电的时候调用RegCopyFile函数将整个注册表保存为外存上的一个文件。当系统重新启动时,我们再调用RegRestoreFile函数将文件全部读出RAM中,然后再热启动系统,我们保存得注册表就可以生效了。值得注意的是这次热启动是必须的,因为只有在系统启动的时候才会去检测RegRestoreFile放在RAM里的注册表信息。这种方法的优点是完全可以使用应用程序来实现基于RAM的注册表的保存,而且这种方法相对简单。但是此方法的缺点是需要两次启动。因此效率相对比较低。
2. 第二种方法需要OEM的参与,OEM可以在BSP的OAL层中实现WriteRegistryToOEM和ReadRegistryFromOEM两个函数,它们的声明为:
DWORD ReadRegistryFromOEM(
DWORD dwFlags, // 参数, REG_READ_BYTES_START表示读新的注册表
LPBYTE lpData, // 指向注册表数据的缓冲区,由OS分配
DWORD cbData // 缓冲区的大小
);
BOOL WriteRegistryToOEM(
DWORD dwFlags, // 参数,REG_WRITE_BYTES_START表示写新的注册表
LPBYTE lpData, // 指向注册表数据的缓冲区,由OS分配
DWORD cbData // 缓冲区的大小,0表示到达注册表尾部
);
Windows CE会在系统启动和关闭的时候调用这两个函数来保存和恢复注册表。此种方法虽然可以避免两次启动,但是困难的地方是ReadRegistryFromOEM函数的实现比较困难,因为在系统启动的时候,块设备驱动和文件系统的驱动都还没有加载,因此不能使用CreateFile,ReadFile这样的文件系统API来实现ReadRegistryFromOEM函数,只能使用一些更底层的操作来实现。
3 设置基于HIVE的注册表
在PB中加入"Hive-based Registry",实验平台:CPU:S3C2410;外部存储设备(Flash)K9F1208UOM 打开%BSP%/Files/platform.reg,找到如下信息:
; HIVE BOOT SECTION
[HKEY_LOCAL_MACHINE\init\BootVars]
"SystemHIVE"="system.hv"
; "PROFILEDIR"="Documents and Settings"
"Start DevMgr"=dword:1
"RegistryFlags"=dword:1
[HKEY_LOCAL_MACHINE\init\BootVars]
"DefaultUser"="default" "SYSTEMHIVE"的值为系统HIVE文件的路径。"Start DevMgr"是一个布尔值,指示是否开始就执行设备管理器device.exe,只有想把系统HIVE存储在对象存储中才在此设置为0,所以这里我们要设置为1。可以在上述的注册表位置下输入"DefaultUser"="",指定默认的用户名。如果是单用户系统,可以不设置在“; HIVE BOOT SECTION”和“; END HIVE BOOT SECTION”之间的所有驱动程序的注册表信息中都加入下列一个标志:
"Flags"=dword:1000
这个标志是一个位掩码,它可以和其它已经存在的"Flags"或运算。值1000表示此驱动程序只加载,这样device.exe就不会把当前驱动程序加载两次了。
保证将包含系统HIVE的文件系统驱动程序的注册表信息和存储设备的驱动程序的注册表信息被包含在“; HIVE BOOT SECTION”和“; END HIVE BOOT SECTION”之间,在这两个语句之间的注册表数据全部属于引导HIVE。
[HKEY_LOCAL_MACHINE\System\StorageManager\AutoLoad\FlashDrv]
"DriverPath"="Drivers\\BlockDevice\\FlashDrv"
"LoadFlags"=dword:1
"MountFlags"=dword:11
"BootPhase"=dword:0
"Flags"=dword:1000
[HKEY_LOCAL_MACHINE\Drivers\BlockDevice\FlashDrv]
"Prefix"="DSK"
"Dll"="FLASHDRV.dll" //调用Flash驱动
"Order"=dword:0
"Ioctl"=dword:4
"Profile"="FlashDrv"
"FriendlyName"="MS Flash Driver"
"MountFlags"=dword:11
"BootPhase"=dword:0
"Flags"=dword:1000
; Bind BINFS to the block driver
[HKEY_LOCAL_MACHINE\System\StorageManager\Profiles\FlashDrv]
"DefaultFileSystem"="BINFS" //建立BINFS文件系统
"PartitionDriver"="mspart.dll"
"AutoMount"=dword:1
"AutoPart"=dword:1
"MountFlags"=dword:2
"Folder"="MYFlashDisk" //实现可以读写的文件夹
"Name"="Microsoft Flash Disk"
"BootPhase"=dword:0
"Flags"=dword:1000
上面的信息添加到platform.reg的“HIVE BOOT SECTION”和“END HIVE BOOT SECTION”之间, 其中"Folder"="MYFlashDisk"文件实现可以读写文件目录MYFlashDisk
注册表信息被保存到此文件夹,系统冷启动后会到此文件夹下读取上次用户基于注册表的设置。
需要源码可以访问www.bluemcu.com
结语:
本文讨论了Windows CE基于HIVE的注册表的在线修改和保存,分析了Windows CE注册表的加载过程,完善了嵌入式系统实际应用中的问题,使得目前的Windows CE运行版本更加接近与桌面版Windows系统。希望能带给读者一些帮助。
免责声明: 凡注明来源本网的所有作品,均为本网合法拥有版权或有权使用的作品,欢迎转载,注明出处。非本网作品均来自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。