WinCE注册表

WinCE界面长得很像普通PC上使用的Windows系统,让人误以为基于WinCE的开发和普通Windows开发区别不大。很不幸,它们还是有非常多的区别,因为WinCE是针对小型移动设备,而这类装置是千差万别的。由于微软只提供WinCE内核,它并不直接支持PC 的硬件,因此几乎所有外部的硬件驱动都需要用户根据所选择的芯片来写驱动程序,这给开发者带来了很大的麻烦。所以,开发者必须了解目标设备和部署应用程序的方式,例如注册表是如何工作的就是其中之一。

1、WinCE注册表概述

1)WinCE注册表

     在微软的嵌入式操作系统WinCE中,注册表扮演着非常重要的角色。与桌面Windows一样,WinCE注册表(Registry)也是一个系统数据库,用来保存应用程序、驱动程序、用户的设定以及其它一些系统的配置信息,通常还存储着操作系统运作和调用程序的状态信息。它的结构与磁盘的逻辑结构相似,是采用树形结构来管理配置信息。例如,每个用户的配置文件、安装的应用程序以及每个应用程序可以创建的文档类型、文件夹和应用程序图标的属性表设置、系统上存在哪些硬件以及正在使用哪些端口等。

2)注册表的作用

     一般来说,注册表控制所有应用程序和硬件外设驱动,控制的方法是基于用户和计算机的,而不依赖于应用程序或驱动本身。例如,每个注册表的参数项控制一个用户的功能或者计算机功能。在没有注册表的情况下,操作系统是不能获得足够的信息来运行和控制外设、应用程序及正确相应用户的输入。

     对于外设来说,注册表是一个记录驱动设置和位置的数据库。当操作系统需要存取硬件设备时,它就需要使用外设驱动程序。但是在WinCE这个外设驱动是独立于操作系统的所以操作系统需要知道从哪里可以找到它们,例如,文件名、版本号、其他设置和信息。因此,注册表没有此设备的记录时,它们就不能被使用。

     对于应用程序来说,当一个用户准备运行一个应用程序时,注册表提供应用程序的信息给操作系统,这样应用程序就可以被找到。因为注册表保存了应用程序的缺省数据和辅助文件的饿位置信息和其他可选项,同样也保存了其他的安装信息,安装软件的版本号、序列号等。

3)注册表的根键和函数

     WinCE注册表和其他windows操作系统的注册表概念和结构基本相同,例如WinCE的注册表的限制有:键名最大长度255个字符、数据最大4k、子键深度最大值16层。WinCE支持四个根键描述如下:HKEY_LOCAL_MACHINE,硬件和驱动配置数据;HKEY_CURRENT_USER,用户配置数据;HKEY_CLASSES_ROOT,OLE和文件类型匹配配置数据;HKEY_USERS,适用于所有用户的数据。

    另外,WinCE操作注册表的函数有:打开RegOpenKeyEx 和创建RegCreateKeyEx;读RegQueryValueEx写RegSetValueEx;枚举入口或子键RegEnumValue、RegEnumKeyEx;删除入口或子键RegDeleteValue、RegDeleteKey;关闭RegCloseKey等。

2、WinCE注册表的实现方式

     嵌入式系统的特点是小型化,因此一些嵌入式设备是没有外存的。为此WinCE注册表提供了两种实现方式:基于RAM的注册表(RAM-Based Registry)和基于Hive的注册表(Hive-Based Registry)。在定制内核的时候只能选择其中一种,从理论上讲这两种注册表都能够实现永久保存注册表数据。注册表实现类型对于用户和应用程序来说是透明的,但是采用不同的类型会影响WinCE的启动顺序和启动速度,还会影响内存的使用量。

1)基于RAM的注册表

     基于RAM的注册表,也叫基于对象存储(Object Storage)的注册表。正如其名,基于RAM的注册表把整个注册表作为一个对象存储堆存放在系统的内存中。这意味着如果对系统进行冷启动或者系统断电,对注册表的所有改动都会丢失。优点是使用基于RAM的注册表,对注册表的读写访问操作会变得非常高效。因此,基于RAM的注册表比较适用于没有外部存储,而且有电池保存内存数据(battery-backed RAM)的设备,它适合频繁热启动而不冷启动的设备。

     如果有外存且经常冷启动的设备采用基于RAM的注册表,则需要在系统断电的时候对注册表进行保存,等系统再次启动时再对保存的注册表进行还原。为此,WinCE提供了两种方法用来断电保存基于RAM的注册表:

i)第一种方式是在设备关闭前调用RegCopyFile函数,将整个注册表数据以文件形式保存到永久存储器上。WinCE提供了两个系统API用来保存和还原整个注册表。当要保存和恢复注册表时,先在系统断电的时候调用RegCopyFile函数将整个注册表保存为外存上的一个文件;当系统重新启动时再调用RegRestoreFile函数将文件全部读出RAM中,然后再热启动系统,先前保存的注册表就可以生效了。

     需要注意的是,这时必须多一次热启动才能使恢复的注册表有效。因为只有在系统启动的时候才会去检测RegRestoreFile放在RAM里的注册表信息。但是此方法的缺点是需要两次启动,因此效率相对比较低。

ii)第二种方式是利用OEM函数。这一种方式可以避免前一种方式需要两次启动的缺点。OEM可以在BSP的OAL层中实现WriteRegistryToOEM 和ReadRegistryFromOEM两个函数。Windows CE会在系统启动和关闭的时候自动调用这两个函数来保存和恢复注册表。当应用程序调用RegFlushKey函数时,这个函数会调用WriteRegistryToOEM函数写注册表数据到永久存储器上。

     此种方法虽然可以避免两次启动的缺陷,但问题是在内核启动时,调用ReadRegistryFromOEM之前文件系统驱动程序还没加载,因此无法使用CreateFile,ReadFile API来打开、读取文件,而只能使用一些更底层的操作来实现。因此,建议如果要采用基于RAM的注册表保存机制,而且要求永久保存注册表数据,使用第一种方式比较容易实现。

2)基于Hive的注册表

     基于Hive的注册表是把注册表数据存放在文件系统的文件上,这种文件被称作蜂箱Hive。这就意味着不再需要在系统断电和启动时进行保存恢复注册表操作。Hive是注册表中的一组键,包括子键、键值、数据,它是保存或者加载注册表数据的单位。

     Hive在文件系统上表现为单个文件,分为:①Boot Hive,包括HKEY_LOCAL_MACHINE, HKEY_CLASSES_ROOT, KEY_USERS中的所有数据,一般只在启动时使用。②System Hive,包括OEM的HKEY_LOCAL_MACHINE, HKEY_CLASSES_ROOT, HKEY_USERS的所有数据,是指设备范围内不随着用户改变而改变的数据。③User Hive,包括HKEY_CURRENT_USER的所有数据,是指用户特有的设置,每个用户都有一个单独的User.hv。

     基于Hive的WinCE注册表加载过程可分为两部分:boot.hv和system.hv。前者是启动时的注册表项,后者是系统注册表项。所谓Hive注册表就是先加载boot.hv,把注册表保存所在的存储驱动和文件系统先加载;然后再加载system.hv,也就是从磁盘上去读系统的注册表项。在启动时加载boot.hv的标签是HIVE BOOT SECTION 和END BOOT SECTION。

     基于Hive的注册表适用于有永久存储并且需要经常冷启动的设备。因为基于Hive的注册表把系统数据和用户数据分开存放,这就意味着基于Hive的注册表可以提供多用户支持。例如,为对每个用户提供不同的User.hv,当用户登录时加载相应的User.hv,从而达到多用户目的。

3、WinCE加载注册表的步骤

     WinCE采用新的注册表保存技术,基于Hive的注册表是让人很兴奋的事情。在这之前基于WinCE的设备,大多数采用给RAM供电方式来保存注册表数据,虽然也可以通过RegCopyFile函数永久保存,但毕竟启动时还要再热启动一次。有了基于Hive的技术,启动系统会自动加载数据,免去了热启动的麻烦。而且当内核更新升级时,不用再担心保存在永久存储器上的系统HIVE文件影响新的内核,因为系统会自动判断并删除过时的系统HIVE文件。

     实际上,也可以认为只有拥有了这样的技术,基于Windows CE的产品才算是一个真正的电脑。现在以基于Hive的注册表为例,简述WinCE在启动时是如何加载已保存的注册表数据:

1)nk.exe执行,启动filesys.exe。filesys.exe首先加载Boot Hive,此时Boot Hive位于nk.bin解压之后的文档中。然后,filesys.exe启动device.exe后处于等待状态,等待device.exe将包含System Hive的文档系统和存储设备的驱动程序加载完毕,而这个文档系统和存储设备的驱动程序存在于Boot Hive中。

2)device.exe加载上述所说的文档系统驱动和存储设备驱动,使之开始工作。之后device.exe处于等待状态。然后,filesys.exe再被唤醒,加载并且安装System Hive,然后filesys.exe再次处于等待状态。

3)nk.exe按照System Hive的信息开始执行初始化工作,包括加载驱动和启动一些应用程序。其中加载驱动一般由device.exe执行,而启动应用程序由filesys.exe执行。这时device.exe和filesys.exe都被唤醒。

     因为Boot Hive和System Hive可能有重复的地方,所以可能重复加载了驱动或重复启动了应用程序。为此,WinCE允许在描述驱动程序的注册表信息中加入防止重复的标志,而应用程序是采用事件对象来防止重复启动。

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/hao507/archive/2009/12/23/5055167.aspx

 

Windows CE 6.0有4个基本的注册表键值, HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, HKEY_USERS。其它的都是这4个注册表的子键。

我 们以一个内建的串口驱动为例,它在注册表文件Platform.reg中的描述如下: 其中Prefix 和 Dll项是必不可少的,Prefix代表设备文件名前缀, 与Index合用表示该设备的名称,该注册表子键的设备名称就是"COM1:",该名称可以用于CreateFile调用。Dll则是动态链接库名称。 Index为设备序号。Flags为1表示系统启动时不加载,需要应用程序自己加载,为0表示该驱动在系统启动时加载。

              [HKEY_LOCAL_MACHINE\Drivers\BuiltIn\Serial]
              "Prefix"="COM"
              "Dll"="$(_TGTPLAT_PFX)_serial.dll"

              "Flags"=dword:0
              "Index"=dword:1

在%WinCE Dir%Public%Common%OAK%INC%目录下,文件cregedit.h中,定义了一个类CRegistryEdit来封装了注册表的操作。许多的硬件驱动,比如串口类,也继承了CRegistryEdit类。

还有一种方法是利用windows CE提供的API进行注册表项的操作。

方法一: 利用系统提供的注册表类CRegistryEdit     

               类的定义在文件regedit.h中。    

               在 构建函数中,会取得当前注册表子键的HANDLE句柄。有3个构造函数,第一个是用全路径,调用hKey = OpenDeviceKey(TEXT("HKEY_LOCAL_MACHINE\\Drivers\\BuiltIn\\Serial"))构造, 第二个是如果已知其父注册表子键,调用RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("Drivers\\BuiltIn\\Serial"), 0,0,&hKey). 第三种方法是用RegCreateKeyEx().

              析构函数中,调用RegCloseKey(hKey)关闭掉对注册表子键的引用。

               读取注册表项可以使用GetRegValue方法,写入注册表项使用RegSetValueEx方法。其方法的实现也是通过windows CE API,具体可以参照下一个Section。

              RegGetList和RegSetList方法提供了对类型为REG_MULTI_SZ和DWORD的VALUE的读写操作。

              其它类方法GetWindowInfo, GetIsrInfo,GetPciInfo获取注册表更多的信息。

  

方法二: 利用windows CE API

              为 了获取一个注册表键值,先要调用RegOpenKeyEx。以上面内建串口驱动为例,RegOpenKey( HKEY_LOCAL_MACHINE, TEXT("Drivers\\BuiltIn\\Serial"), 0, 0, &hKey ), 其中hKey就是我们获取的该注册表子键的HANDLE句柄。接下来对注册表子键的操作就是通过hKey来实现.

              有了hKey, 就可以对注册表子键的各个内容进行读写操作。如果要读去子键的Prefix, 调用函数RegQueryValueEx(hKey, TEXT("Prefix"), NULL, &lpType, &lpData, &lpcbData), lpType, lpData为Prefix返回类型和值,该例中,lpType = REG_SZ, lpData = TEXT("COM"). lpcbData当调用时,修饰限制lpData的size in bytes,返回时,为lpData返回值的SIZE。

              对应于读操作,写操作是一个相反的过程,RegSetValueEx(hKey, TEXT("Prefix"), NULL, REG_SZ, PBYTE(TEXT("TST")), wcslen(TEXT("TST"))*2). 其中要写入的项为Prefix项,类型为REG_SZ, 值为TEXT("TST"), 最后一个参数为写入值得SIZE in bytes. 注意第二个参数,如果注册表中存在该项,则改写它的值。如果没有,则新建一个注册表项。

              某些情况下,我们需要删除一个注册表项,只需调用RegDeleteKey(hKey, TEXT("Index"))就可以删除Index注册表项。

              要关闭一个注册表子键,只需要调用RegCloseKey(hKey)就可以完成。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值