概述
第二章 Windows CE系统结构
一般认为Windows CE是一个适合嵌入式应用的通用操作系统,然而,从系统的角度来看,Windows CE并不只是一个操作系统,它还包括对多种目标处理器以及外围设备的支持,并提供了系统开发工具、应用开发工具、整合的应用程序 (例如IE),以及.NET Frameworks等等,所有这些组件构成了Windows CE系统的应用框架:在操作系统的基础上,1) 提供方便的工具来开发BSP,使得基本的Windows CE操作系统kernel可以迅速被移植到某个专用嵌入式系统的硬件平台上;2) 提供便捷的应用软件开发平台,以及应用程序在多种Windows平台间的快速移植能力;3) 操作系统以及所支持的特性可以根据嵌入式应用程序的需要,进行配置管理,使开发者可以根据需求来选择系统特性进行组合,建构出新系统。
本章主要从宏观的角度,来分析整个Windows CE的架构。为了避免混淆,在没有明确说明的情况下,本书中Windows CE指操作系统本身。
2.1 透视系统关键特性
Windows CE (包括开发平台) 相当适合嵌入式应用程序的开发,它希望提供给使用CE操作系统来做嵌入式产品开发的人,如下的基本特性:
l 适应小型系统,为低成本计算能力较差的系统提供简洁、高效、完善的控制机制
l 支持多种处理器和计算机架构,并支持多种装置接口
l 遵循Windows平台的应用开发规范:提供Win32 API等
l 操作系统各部分模块化,可根据特性订制,以适应ROM,并以最佳的方式使用内存
l 为应用程序提供网络通讯、图形使用者接口、数据库、档案等支持
l 支持实时应用
l 提供进阶电源管理功能
这些特色使得Windows CE (包括开发平台) 成为一个成功的商用系统。下面将从几个方面来检视系统所提供的具体能力。
2.1.1 操作系统kernel特性
1. 内存架构
Windows CE提供了灵活的内存存取机制,使系统中不同类型的应用程序可以充分的使用系统提供的RAM、ROM以及Flash Memory,并选择性的有效利用处理器提供的虚拟内存,内存保护等功能。内存管理可以划分为三个部分:实体页面管理,主要负责追踪系统中物理内存的使用情况,为换页程序选取可用的实体页面,释放不使用的实体页面等;虚拟内存管理,主要管理系统的内存地址对应页面的换进换出等;heap管理,主要管理处理程序空间内部的动态内存释放与回收,以支持程序的动态数据结构。
系统中的32位虚拟地址提供了4GB的虚拟内存空间,对于嵌入式应用来说,内存一般很小,因而系统在使用内存方面作了些限制,以提供更高效能的储存空间管理。这些限制包括:大量的系统保留空间,实际上这些地址空间,通常不对应到任何的实体页面;系统处理程序数最多只有32个,每个处理程序的实际可使用内存空间受到限制 (32MB);有固定的处理程序共享内存;有ROM地址的对应等。
Windows CE使用如图2.1的内存配置 (memory layout)。
图2.1 Windows CE的内存配置
由于限定了处理程序空间的大小和处理程序的数目,内存配置 (memory layout) 变得相对简单,系统提供33个Slot供这些处理程序使用,其中,Slot 0是全域的共享内存,底部的一些Slot由重要的系统处理程序使用,kernel部分的静态虚拟地址 (Static Virtual Addresses) 专门用来对应ROM、外围设备等资源。NK Slot即NK.EXE的处理程序空间,NK.EXE是一个在kernel mode的处理程序,包括了操作系统kernel的程序代码。对物理内存相对比较紧缺的系统来说,对处理程序空间和处理程序数目的限制,将能有效的纾解内存系统可能的压力。例如,某个应用系统限制6个处理程序,那么系统对应中,将永远不会用到第7个的Slot,系统作地址对应,将不考虑别的部分。更详细的信息请参看第4章的内容。
2. 排程
Windows CE操作系统提供了对多种优先权(multi-priority)进行排程的能力,它的排程器基本上可以看成一个具有增强实时性能、支持更多系统结构、结构简化的Windows XP排程器。表2.1显示了二者主要的差别。
表2.1 Windows XP与Windows CE排程器的比较
| Windows XP | Windows CE |
Process | 处理程序结构比较复杂,系统支持处理程序数目众多。处理程序空间达4GB,可以掌握各种复杂资源 | 处理程序结构比较简单,系统最多支持32个独立的处理程序。处理程序空间32MB |
Thread | kernel基本排程单位 | 基本上与Windows XP相同 |
Fiber | 由使用者自己负责排程,排程代价小 | 基本上和执行绪概念相同,主要是为了Windows兼容性平台应用的 |
SMP | 支援 | 不支援 |
排程算法 | 32级优先队列的FCFS排程,同优先级执行绪采用RR排程。32级可以分成实时(16-31)和普通(0-15)两个类别 | 256级优先队列的FCFS排程,同优先级执行绪采用RR排程。256个基本优先级可以分8个大的级别,持有THREAD_PRIORITY_TIME_CRITICA标志的优先级类别不能被抢占。 |
排程状态 | 排程状态众多,转换关系复杂 | 六种基本状态,转换关系较为简单 |
配额 | 时间配额计算比较复杂,处理桌面任务和服务有较大区别,不同优先级具有不同的配额策略 | 没有时间配额策略,大约采用10ms左右的time slice |
多使用者 | 具有支持多使用者的能力 | 不支持多使用者 |
IPC | 完善的通信机制和通信保护机制 | 不支持命名管道、资源句柄的复制和继承等操作,使用共享内存的形式较为普遍 |
3. 实时能力
Windows CE实时能力的设计目标参考了大量GMPTG的调查研究,它的设计目标可以适应大部分 (95%) 硬式实时 (hard-real-time) 系统的需求:它1ms定时周期的误差约为100μs,在200MHz的x86系统下可以期望达到50μs。实时能力的另一个重要指标是中断延时,在Windows CE中,中断延时和中断处理方式密切相关,当采用在ISR中直接处理时,延时非常短,较长的延时通常发生在采用IST方式处理中断事务的情况,排程系统保证在此种情况下的延时不超过100μs。
在Platform Builder 4.0以上的版本提供了一系列工具进行系统效能的分析,关于使用这些工具测试实时性能的方案,可以参考MSDN中Get Embedded专栏的文章《Testing Real-Time Systems in Microsoft Windows CE .NET》。
4. 装置驱动程序
Windows CE提供了大量的装置驱动程序,在Platform Builder中可以轻易的从一个特定的平台配置中加入或者删除。这些驱动程序涵盖的层面很广,包括了大多数常见的外围设备装置,例如与NE2000兼容的网络卡、标准触控板等。
此外,系统提供了类别驱动程序模型以及底层的类别驱动程序,例如IEEE1394 Firewire设备类型驱动程序,开发者只要根据模型,完成驱动程序的底层实作部分,就可以支持一种具体的1394设备。这些类别驱动程序模型为应用程序提供了一个公共接口,典型的应用模型就是DirectX接口,应用程序开发者可以利用DirectX界面迅速的查询并使用装置驱动程序和硬件能力。关于装置驱动程序的具体技术,请参考MSDN中的相关说明文件。
5. 进阶电源管理
进阶电源管理是设备管理模块的一部分,在Windows CE设备管理中,电源管理器提供了一个符合ACPI标准的电源管理基本接口,并使用设备管理的事件传递机制来处理相关的电源事件。实际上是透过电源管理驱动程序(它是电源管理接口的实体部分)和每种具体的装置驱动程序中的电源管理程序来进行电源管理。
2.1.2 应用系统基础组件
1. 应用程序设计界面
Windows CE提供了符合Windows平台标准的开发环境,它是Win32 API的一个子集,涵盖了大部分的Win32功能。在接口的语意方面,Windows CE对Win32 API函数有限制,例如,关于处理程序管理的函数中,它不支持处理程序的一些环境设置,像是处理程序的资源配额等。类似的情况在接口的实作里会陆续看到。
Windows CE Application Frameworks也包括了MFC和ATL,它们主要用来支持使用Microsoft Visual C++ 语言开发Windows CE的应用程序,类似Win32 API,二者皆提供了应用接口层在Windows平台的可移植性。
1) MFC提供了Windows平台应用程序开发的基础类别库,包括了诸如接口、数据存取、事件机制、Windows控件、ActiveX、网络等各方面的对象﹔程序开发者可以使用这些类别配合Microsoft Embedded Visual C++工具建构包括了简单的对话框程序甚至复杂的文件档案程序 (Multiple Document)、多媒体程序、数据库程序等应用程序。
Windows CE的MFC和一般版本的MFC也有区别,它提供了9个特有的类别,例如:CCeCommandBar、CCeDocList、CCeDBDatabase等;有的则是部分类别不同,例如:CBitmap、 COleControl、CBrush、CButton等;除此之外,大部分的类别和一般版本的MFC是一致的。MFC全域函数的情况也是类似。从其它Windows平台移植应用程序的时候 (当然这种情况并不经常发生,而且主要在一些局部功能上可以完成) 需要注意这些不同。
2) ATL和COM的关系不言而喻,在应用层上,ATL主要包含了基于COM组件技术的OLE2和ActiveX,在一般情况下,ATL用来实作ActiveX的Server,大多数的Windows CE ATL类别和一般版本是相同的,只有13个不同或者不被支持。这一特性使得在多种应用程序中广泛使用的ActiveX控件,例如:图表控件、Office文件档案控件、Windows Media控件可以在Windows CE的应用中使用,使应用程序开发的难度大幅降低。例如,当我们在一个基本的系统配置之中增加Windows Media Player (ActiveX控件) 之后,系统便具有播放mp3音乐、播放DVD视讯的基本能力,这几乎不需要付出额外的开发代价。
3) Windows CE使用了.NET Frameworks的架构,它能够提供Windows应用平台最大的兼容性,原则上,基于.NET的任何应用程序均可以在任何一个.NET执行环境中正常运作,当然包括Windows CE的.NET Frameworks,它将是未来Windows应用平台的发展方向:基于.NET技术的应用开发模式将逐渐取代传统方式的开发模式,成为包括嵌入式产品中应用程序开发的主流模式。这一点类似Sun Microsystems的Java技术 (J2ME正是为了适应嵌入式需要而设计的Java Frameworks标准)。
2. 网络通讯
Windows CE网络模块的设计目标主要包括以下四点:
1) 高效能:提供最好的网络 (无线和有线) 应用平台
2) 兼容性:支持多种网络类型和选项
3) 易使用:透过系统提供的API,使用者可以轻易的开发出各种网络应用程序。
4) 模块化:这是整个网络系统架构的特征,系统可以拆成很多个独立的部分,应用系统可以根据需要,选择其中的一部分,这样可以降低系统成本,使得系统更加精简。
图2.2 Windows CE 网络通信模块架构
以上的目标应用在网络模块的分层结构和设计上。如图2.2所示,模块可以分为:服务层,它们是网络协议堆栈 (network protocol stack) 的应用层协议,提供网络服务,这些服务处理程序一般由Services.exe控制,藉由Winsock API提供具体功能;接口层,这一层实际上是系统的标准应用接口,这一层隐藏了网络的底层实作部分,减低Windows平台在网络应用的平台相关性。如果你愿意,甚至可以在这一层实作BSD Socket等公共接口,使得UNIX网络应用也可以轻易的移植到上面来;协议层包括各种协议堆栈,构成了支持多种网络类型的关键,一个新的网络类型可以藉由一个新的协议堆栈和相应的底层程序来达成,使得应用程序在不知不觉间就可以使用新的网络特性;驱动层是实体设备的支持基础,它可以分成两个子层,上层是驱动模型以及接口,主要是NDIS接口,它由网络驱动程序负责,NDIS也定义了不同的驱动模型,包括协议驱动、中间层驱动以及miniport drivers 等。
3. 数据储存
Windows CE 提供了三种类型的档案系统:基于RAM的档案系统、基于ROM的档案系统、以及用于支持ATA (Advanced Technology Attachment) 设备和SRAM卡等周边储存设备的FAT档案系统。其中,前两种档案系统属于Windows CE的内建档案系统,后者属于可安装的文件系统。另外,嵌入式系统的开发人员也可以编写自己的档案系统并在系统中注册使用。不论储存设备属于何种类型,所有对档案系统的存取都是透过Win32 API完成的,Windows CE藉由这种方式提供与设备无关的档案存取特性。
RAM内存是Windows CE平台预设使用的储存设备,最多可达256MB。Windows CE设备使用的RAM内存与个人计算机所使用的RAM不同,由于在关机的情况下仍有电源供应,因此关机后数据也不会遗失。对象储存在Windows CE扮演的角色相当于个人计算机上的硬盘,它提供应用程序及其相关数据一个可靠稳定的储存空间。除了用于存放档案之外,对象储存中还储存着系统的注册表以及Windows CE数据库。
与对象储存相关,基于RAM的档案系统和基于ROM的档案系统是Windows CE预设支持的内建档案系统。除此之外,使用者还可以安装支持周边储存设备的档案系统,比如FAT、UDFS等。对周边储存设备的存取就是透过这种可安装档案系统来完成的。另外,还可以将一个周边储存设备切成多个分割区并分别加载,其中每个分割区可以使用不同的档案系统。Windows CE没有像个人计算机那样使用磁盘驱动器代号,加载后的磁盘分割区以目录的方式呈现。
4. 图形使用者接口
Windows CE整合Microsoft Win32 API,使用者接口,及GDI (Graphics Device Interface) 的函式库,建构了GWES (Graphics,Windowing,and Events Subsystem) 模块 (GWES.exe)。GWES是介于使用者、应用程序及操作系统间的一组接口,它支持了所有用来提供使用者控制应用程序的Windows CE使用者接口,包括了:窗口、对话盒、控件、选单、以及资源。GWES也提供了使用者关于bitmaps、carets、光标、文字、及图标的相关信息,即使是缺乏图形使用者接口的那些Windows CE平台仍是使用GWES基本的窗口与讯息功能及电源管理函式。
5. 多语言和国际化支持
使软件能够适用于不同的语言、文化、及硬件上,称之为国际化支持。国际化的目的在于让使用者即使在使用不同语言版本的产品时,也能够有一致的外观、感受及功能。举例来说,使用者会期望中文化之后的软件也能够提供与原先语言版本的产品一致的功能,并且期望两者能够有一样的质量,他们也希望能够在不同语言的版本之间正常而顺利的互动及运作。
Windows CE提供了大量的字符码支持,而在语言文化上的常规方面,则是藉由Unicode及国际语言支持 (NLS,National Language Support) 来提供。Unicode是一种通用的字符编码系统,而NLS则是用来记录关于日期、时间、数字、及货币格式的相关信息,NLS藉由操作系统的支持来针对各个地区提供关于排序与字符型别的信息。除了字符及地区的编码之外,国际化也包括了对手写辨识引擎的支持,手写辨识引擎对于东亚语系及多语言使用者接口 (MUI,即 Multilingual User Interface:主要让使用者能够对语言及地区进行切换的使用者接口) 的使用者来说,是相当有用的。此外,国际化支持多种专为特定东亚语系设计的输入法及输入法编辑器。
注:东亚语系之所以需要输入法编辑器,是为了能够从键盘或手写板输入字符。
1) Unicode
Windows CE在kernel中即支持Unicode字符集标准,包括中日韩等国的语言支持。Unicode标准定义了一套统一的字符编码标准,它需要用一对16位的数表示一个字符,这种特性可以保证用16位的编码空间来支持使用超过65535个字符的语言。对这一特性,Windows CE并没有提供完全的支持,因为在多数应用中,系统并不支持编辑,而只有显示方面的能力。
2) 多语言使用者接口
MUI是Windows 2000/XP所具有的诱人特色之一。在Windows CE中,这一特色也被引入,开发者可以透过MUI函数设计支持多种语言操作接口的软件。因为系统具有良好的多语言显示能力,同时微软提供了大量优美的字型文件,使用者可以很轻松的按照实际的需要来建构接口上的语言显示。
3) 输入法
输入法是用来输入类似汉语这样构成复杂(并非由子母构词)之语言的输入工具。在系统的国际化支持中,主要包括了中日韩三国语言的输入法,其中以汉语输入法最为复杂,基本输入法的使用和功能与典型的Windows系统的输入法相似,只是功能更加精简,资源消耗更加少。
图2.3 Windows CE 安全体系
6. 安全
Windows CE提供安全机制协助使用者建构安全的网络通信 (藉由SSL)、安全数据储存、标准加密体系、标准认证机制等等。系统主要提供了三个模块来支持安全系统的机制:CryptoAPI安全服务接口 (SSPI,即 Secure Support Provider Interface):由SSP (Secure Support Provider) 来实作Winsock的SSL (通过实现SSPI的服务者)。图2.3表示应用程序和这三个模块之间的关系图。
7. 应用整合
Windows CE为了使系统开发更加方便,随同开发系统提供了很多应用,系统开发者可以将这些经过授权的应用连同产品一同出售。这些应用常见的包括:浏览器产品Internet Explorer,适合嵌入式应用的Office组件 (例如Pocket Word),Windows Media技术,RDP (Remote Data Protocol) 远程桌面客户等等。
图2.4 Platform Builder系统配置检视表
2.1.3 嵌入式系统支持
1. 高度模块化,系统配置具有弹性
嵌入式操作系统的一大特点就是可精减,可配置所需的系统模块。Windows CE的这一特性很明显,它具有一个很小的核心NK,基本上只包含了排程、内存管理和kernel API,它们构成了一个完整个体,其余大部分功能都在单独的模块中完成。例如档案系统 (filesys.exe),图形使用者接口 (gwes.exe),装置管理 (device.exe),服务管理 (services.exe) 等等。同时,在这些大的模块内部,良好的结构也支持更细致的模块化,譬如通信模块的模块化程度就很高,具有很大的可扩展性。在Windows CE中,每一个功能模块可以称之为一个特征。这些特征可能是独立的,也可能有一些依存关系:例如Win32 API中有一组函数专门支持fiber执行绪,这也是一个特性,有很多应用模块,例如:多媒体应用和数据库服务就利用到这个特性。Windows CE提供了专门的开发工具来管理这些特征,并且可以追踪这些关系。于是,开发者可以藉由一定的步骤选择一些特征进行组合,产生一个开发用的原型系统,而背后的模块组织、编译、装配等工作,则可以藉由这些工具来完成。
系统的配置可以在Platform Builder中完成。透过在如图2.4的检视表上的操作,就可以在系统配置中增加或者删除特征,之后则是用系统建构工具完成这个配置,使之成为一个可实际运作的系统映像文件 (image)。
可配置性的秘密隐藏在建构操作系统映像文件的过程当中。这个映像文件包括了操作系统的kernel,内存中的档案系统,储存的程序和文件,系统配置文件,注册表数据库等等。整个建构过程可以分成4个阶段:CESYSGEN、BSP、BUILDREL、MAKEIMG。
(1) CESYSGEN
这一阶段透过cebuild.bat和sysgen.bat来进行控制。根据项目配置产生基本的系统配置文件,它们主要处理四类档案:bib,说明需要涵盖在映像档里的Windows CE档案;dat,档案系统描述,例如某个程序档案的储存位置;db,Windows CE对象储存数据库的描述;reg,系统注册表。
整个处理阶段可以看成是对以上几种档案的前置处理过程,主要工作就是将系统里这类档案的模板改成符合系统需求的形式,好像一个转换程序一样 (图2.5所示)。
图2.5 CESYSGEN的工作
程序代码2.1是一个实际处理的例子。
程序代码2.1 CESYSGEN 对配置模板的前置处理
//范本文件(片断) |
; @CESYSGEN IF FILESYS_FSREGHIVE ; HIVE BOOT SECTION [HKEY_LOCAL_MACHINE/init/BootVars] "SYSTEMHIVE"="Documents and Settings//system.hv" "PROFILEDIR"="Documents and Settings" "Start DevMgr"=dword:0 ; END HIVE BOOT SECTION ; @CESYSGEN ENDIF FILESYS_FSREGHIVE |
//输出档(对应的片断) //当系统定义了名为FILESYS_FSREGHIVE的环境变量时,结果为 |
; HIVE BOOT SECTION [HKEY_LOCAL_MACHINE/init/BootVars] "SYSTEMHIVE"="Documents and Settings//system.hv" "PROFILEDIR"="Documents and Settings" "Start DevMgr"=dword:0 ; END HIVE BOOT SECTION |
//否则@CESYSGEN IF和@CESYSGEN ENDIF这两个标签中间的部分不会包括在输出当中 |
(2) BSP
这一阶段Windows CE工具系统将编译连结被包括在特征中的任何BSP驱动程序以及OAL程序代码。这一阶段系统会使用两类档案来确定需要哪些原始程序代码或者链接库档案:系统配置 (需要编译那些模块) 和MAKEFILE文件 (编译那些程序代码,使用什么样的规则编译)。后者和一般的make系统使用的MAKEFILE不一样,它包括两个档案,DIRS和SOURCES,前者纪录程序代码的位置,后者则是每一个档案的编译规则。
(3) BUILDREL
这一阶段的工作主要是复制:将那些已经编译好的东西以及系统所需的各种档案复制到一个特定的目录下。这些内容即构成建构一个操作系统映像文件的基本内容。
(4) MAKEIMG
建构映像文件时,系统需要做三件事。第一步,将前面产生的配置文件按类别组合成一个主配置文件,名字分别为:ce.bib (bib)、initobj.dat (dat)、initdb.ini (db)、reginit.ini (reg)。第二步,重新配置所有可执行文件的资源以适应当前的语言配置。第三步,对映像档的内容进行布局,例如建构一个只有一个根目录的档案系统,连结装配所有的就位可执行程序 (当映像档背靠背 (back-to-back) 到内存的特定位置后就可以执行的程序),将ROM中的程序对应到档案系统的/Windows目录下。最后产生操作系统映像文件nk.bin。
系统藉由前端开发工具 (Platform Builder的特征浏览和修改工具) 和编译系统的配合建构了简便的系统配置管理机制,在高阶的应用中,Platform Builder提供了配置指导工具,帮助开发者建构适合特定应用领域的基本系统。更加详细的内容请参阅MSDN中Platform Builder的相关内容。
2. 系统易于移植到其它硬件平台
多平台支持是嵌入式操作系统的一个重要特色,一般来说,多系统支持主要在两个层面:1) 系统体系结构,这主要是对处理器的支持,包括编码差异和指令系统定向,前者包含对应系统的中断机制、特权指令 (privilege instruction) 对应、储存管理机制对应、I/O系统对应,后者则由编译系统自动完成;2) 目标计算机 (Target Machine) 的组成,这主要是透过驱动程序来完成。在Windows CE中,这两个部分的主要内容被包在一个称之为OAL (OEM Adaptation Layer) 的硬件隔离层中,依次对应到CSP (CPU Support Package) 和BSP。
Windows CE支持的处理器家族主要包括ARM系列、Intel x86系列、MIPS系列以及SH系列,因为涉及到编译系统的不同和操作系统kernel的稳定性,一般开发商将很难增加新的处理器支持,他们只能修改CSP中相对独立的支持,例如引导程序。对应用系统开发来说,系统移植主要是建构BSP,使得系统可以支持专门用于该系统的主机板以及相关的设备。在Windows CE中也使用了和Windows XP相类似的可扩展韧体接口 (EFI,Extensible Firmware Interface),关于EFI稍后将有介绍。
2.1.4 工具
开发工具是Windows CE的一个重要部分,实际上也是这个系统得以在商业上成功的重要因素,主要是因为它的易用性及强大而完善的功能。其它一些系统,例如:eCos也提供了类似Platform Builder开发工具,但是显然这个工具不够成熟、不太好用,并且在建构系统时会有较多的问题。
1. Platform Builder
Platform Builder用于建构使用Windows CE操作系统的嵌入式平台,用某一个特定硬件平台的Windows CE操作系统和基本应用环境来辅助开发。从工具的角度来看,这是一个整合的开发环境,包括了基本的本文编辑功能、多目标编译侦错工具、特征编辑器、SDK汇出工具 (透过它可以为当前平台建构一个在Embedded Visual C++中安装的SDK)、指导手册工具以及用于测试、性能分析等工作的多个工具。更多的内容请参考第14章。
2. Windows CE Application Frameworks
工具的核心是Embedded Visual C++,这个工具具有和Visual C++ 6相同的基本特性,包括对MFC、ATL以及COM/DCOM的支持、应用程序指导手册、编译侦错等多种功能。因为这种相似性使得传统的VC程序设计师可以很容易的转移到嵌入式领域作应用软件的开发。此外在早期版本中还包括Embedded Visual Basic,这是VB的一个嵌入式精简版本,更新的版本目前还没有加进Windows CE Application Frameworks。.NET类型的应用则不使用它们。
MFC、ATL、以及RTC也包括在这个工具体系中,2.1.2节对此已经做过一些说明。更详细的内容将在第13章介绍。
3. Emulator
Emulator是Windows系统上的一个应用程序,它可以执行经过特定编译处理 (Emulator本身也可以视为一个独立的平台) 的Windows CE系统。Emulator提供了相当多的硬件特征仿真,例如显示、声音、USB接口、网络等。它和Platform Builder以及Embedded Visual C++均可整合在一起,透过KITL可与适配卡相连,充当目标平台。如此一来,开发者可以脱离实际硬件开发、侦错、测试在Windows CE上执行的应用程序,当硬件平台和基本操作系统环境建构完成后,这个应用程序几乎不用修改就可以正确的执行。这个特性使得底层开发和应用程序开发可以并行工作,大大的缩短了开发周期。目前,Emulator只支持Intel x86系统架构下的仿真。
2.2 程序代码架构
2.2.1 原始程序代码树的构成
安装Platform Builder (选择安装共享原始程序代码) 以后,在WINCE400目录下会有PLATFORM、PRIVATE、PUBLIC、SDK、OTHERS几个目录。
l PLATFORM里面按照不同平台存放的是BSP,例如CEPC平台,包括平台特定的驱动程序、引导程序、图形引擎的部分驱动程序、核心HAL驱动程序等。
l PRIVATE是Windows CE的共享原始程序代码,主要包括应用服务、资源管理器 (开始菜单接口)、通信支持、数据储存管理器、图形使用者接口以及事件系统、CE操作系统kernel程序代码。PRIVATE目录下的程序代码一般是不希望开发者修改的,因为这可能会与发布出来的Windows CE产品产生兼容性和稳定性的问题。
l PUBLIC存放Windows平台开发工具,包括大量的驱动程序、应用程序开发套件。
l SDK按照平台的系统结构存放各种开发工具、例如编译器等。
l OTHERS的内容包括MFC、ATL的共享程序代码、链接库档案以及.NET的共享函式库。
图2.6和图2.7 显示了部分程序代码树的构成情况。
/ |
WINCE400 |
/ |
PUBLIC |
├─ |
COMMON |
Windows |
平台共享组件 |
│ |
├─ |
CESYSGEN |
│ |
├─ |
DDK |
驱动程序开发工具 |
│ |
│ |
└─ |
INC |
CEDDK |
标头档 |
│ |
├─ |
OAK |
开放平台工具 |
│ |
│ |
├─ |
BIN |
可执行工具程序 |
│ |
│ |
├─ |
CSP |
密码服务支持套件(Cryptographic Service Providers)
|
│ |
│ |
├─ |
DEMOS |
范例程序 |
│ |
│ |
├─ |
DRIVERS |
驱动程序 |
│ |
│ |
├─ |
FILES |
│ |
│ |
├─ |
INC |
通用标头档 |
│ |
│ |
├─ |
LIB |
通用链接库档案 |
│ |
│ |
├─ |
TKTEST |
测试工具 |
│ |
│ |
├─ |
TOOLS |
工具 |
│ |
│ |
├─ |
…… |
│ |
│ |
└─ |
UTILS |
公用程序 |
│ |
└─ |
SDK |
应用程序开发工具 |
│ |
├─ |
INC |
应用程序开发标头文件 |
│ |
├─ |
LIB |
应用程序开发链接库档案 |
│ |
└─ |
SAMPLES |
范例 |
├─ |
DCOM |
DCOM |
开发支持 |
├─ |
DIRECTX |
DirectX |
开发支持 |
├─ |
IE |
Internet Explorer |
开发支持 |
├─ |
RDP |
远程桌面协议开发支持 |
├─ |
SERVERS |
应用服务 |
└─ |
…… |
图2.6 PUBLIC目录结构
2.2.2 程序代码共享
Windows CE并不是直接供最终使用者来使用的操作系统,它的最终使用形式 (可执行程序) 必须由嵌入式系统开发商随他们的嵌入式产品一同发布。系统的原始程序代码则是包含在Platform Builder中,它可以协助系统开发者开发出在 CE 架构上执行的产品。
Windows CE的共享程序代码分为两类,一类是Private目录下的内容,它们的共享受到Microsoft Shared Source License的约束,另一类是其它部分的程序代码,它们的共享条件是Microsoft end-user license agreement。本书使用的程序代码主要集中在Private目录之下,仅有少量CSP的内容在Public下面。需要说明的是本书有些章节内容所涉及到的部分原始程序代码是没有开放的,这些章节包括数据储存部分的档案系统、图形使用者接口的图形引擎等,此外本书未讨论的网络通讯支持的部分原始程序代码也是没有开放的。
2.2.3 建构系统
建构一个可以启动的操作系统映像文件的方法是使用Platform Builder的建构系统工具。根据需要,配置好了一个平台之后,可以使用Build功能选项,这样Platform Builder就会透过编译工具,把各个模块编译连结起来,并做好内存配置,产生启动内存映像文件。不过这种方法在建构系统的时候,主要是分析处理预先编译好的操作系统模块,这些函式库档案存放在Public目录的特定位置,对操作系统本身的程序代码所进行的修改 (典型的是Private下的原始程序代码) 并不会造成相应链接库档案的更新,因此在修正了kernel的错误之后,需要使用命令列手动编译、更新相应的模块。这一操作需要打开Build菜单中的命令列 (打开程序代码目录),转移到模块所在的目录之后使用build –c命令编译更新该模块。之后,再使用Platform Builder的Build工具。
/ |
WINCE400 |
/ |
PRIVATE |
├─ |
SERVERS |
一些 |
appliance |
服务 |
└─ |
WINCEOS |
CE |
程序代码 |
├─ |
COMM |
通信 |
└─ |
COREOS |
CE |
操作系统程序代码 |
├─ |
CORE |
core.dll |
,公共程序代码 |
│ |
├─ |
DLL |
公共函式 |
│ |
│ |
├─ |
xxx |
系统结构相关程序代码 |
│ |
│ |
└─ |
…… |
│ |
├─ |
INC |
CoreDLL |
标头档 |
│ |
└─ |
LMEM |
内部内存堆积管理 |
├─ |
DEVICE |
设备管理 |
│ |
└─ |
LIB |
设备管理、电源管理、随插即用管理、 |
I/O |
资源管理 |
├─ |
FSD |
|
│ |
├─ |
FATFS |
FAT |
档案系统接口 |
│ |
│ |
└─ |
X86 |
│ |
└─ |
…… |
├─ |
GWE |
图形系统以及窗口事件机制 |
│ |
├─ |
INC |
│ |
└─ |
MGDI |
图形接口 |
│ |
├─ |
GPE |
│ |
├─ |
GPEROTATE |
│ |
├─ |
INC |
│ |
└─ |
MULTIMON |
├─ |
NK |
核心程序代码 |
│ |
├─ |
CELOG |
日志 |
│ |
├─ |
INC |
标头档 |
│ |
├─ |
KDSTUB |
核心侦错器 |
│ |
├─ |
KERNEL |
核心:包括排程、储存 |
│ |
├─ |
KITL |
│ |
├─ |
MAPFILE |
│ |
├─ |
NOMAPFILE |
│ |
├─ |
SCHEDLOG |
│ |
└─ |
VERIFIER |
└─ |
STORAGE |
外部非挥发性储存管理 |
├─ |
BUILDEXE |
├─ |
DOSPART |
├─ |
FSDMAIN |
├─ |
FSDSERV |
├─ |
INC |
├─ |
LOAD |
├─ |
NOTIFY |
├─ |
STOREAPI |
└─ |
STOREMGR |
图2.7 PRIVATE目录结构
2.3 系统模型
2.3.1 阶层式的架构
1. 系统分层模型
目前的操作系统 (包括应用环境、操作环境等) 一般具有分层的结构特征,典型的就是UNIX系统的同心环,最里面是硬件,从里向外是kernel、共享函式库、应用程序三个层次。Windows CE的分层结构比较复杂一些 (图2.8),这是根据它适合嵌入式应用的特点所设计的。从提供者的角度来看,图中上面四层主要由微软公司维护开发,下面两层主要由嵌入式产品开发商根据产品需要开发。当然,这个划分并不绝对,而是根据产品需求来决定。需要说明的是,这里并没有一个单独的应用层,因为在大多数情况下,从嵌入式产品发布的方式来看,使用者的应用产品是捆绑销售 (bundle) 的,所以它们本身也是构成应用整合层的一部份。
图2.8 Windows CE的分层
从接口的角度来看,一般系统开发环境包括应用和系统两个接口,用以支持系统和应用程序开发,例如在Windows平台,SDK代表了应用层界面,而DDK代表了系统接口,两个接口之间就是操作系统的实体。图2.8中,CE操作系统的功能在中间两层实作,应用支持库的上部和操作系统层的上部 (主要是CoreDLL.dll,应用支持库中的很多界面也是透过DLL导出到系统中的) 以及下部具有接口性质,它们构成了CE的应用接口和系统接口。因而,从某种角度来看,OAL是系统接口的实作,而上面两层就是应用接口的使用者。
而由层与层的互动来看,主要的互动是发生在相邻两层之间,而上面三层具有一定的向下跨层存取能力。限制存取在一定程度上有助于功能的区隔,清楚的接口也使我们可以方便的置换掉某一层的实作。
2. 移植模型
Windows CE的可移植性在2.1节中略有提到,在CE操作系统结构设计上的主要是藉由移植模型来达到可移植性的目标。从系统特性可以知道可移植性主要反应在两个层面上:应用程序的可移植性以及系统关于硬件平台的可移植性,相应的移植模型也分为应用程序移植模型和系统移植模型。
应用移植模型 (如图2.9) 的核心就是软件接口技术和应用开发工具的软件整合。从图中可以看到,应用层的界面很丰富,其中最基本的就是Win32 API,其次是MFC、ATL这样的接口。.NET则是新一代的Windows应用框架。这些软件层为应用程序提供了应用模型,而开发工具则直接支持这些程序设计模型,例如,VC提供了指导手册工具 (wizard),协助产生程序代码。
图2.9 应用移植模型
图2.10 系统移植模型
系统移植模型 (如图2.10) 协助Windows CE实作广泛的硬件支持。同样是用了工具和软件接口技术整合的形式。这一层的可移植性主要在三个层面:CSP支持不同的处理器系统结构;BSP支持不同的硬件主机板 (I/O、总线等等);驱动程序支持不同的外围。从工具的角度看,开发工具主要是以指导手册的形式协助开发者配置修改一个具体的OAL。驱动模型被包括在Windows CE的类别驱动程序 (详见第6章) 中实作,这些类别驱动程序一般由Windows CE操作系统提供。
2.3.2 模块化的组织
从逻辑功能的角度来看系统架构:如图2.11所示,我们关心的Windows CE操作系统的主体就是两条双黑线之间的部分,下面将逐渐把这张图展开。
图2.11 Windows CE的模块与系统架构
1. 组件剖析
从宏观的角度来看,系统包括以下几个软件组件:CoreDLL,NK,设备管理模块、数据储存模块、图形使用者接口模块、通信模块、OAL模块以及两个比较特殊的部分:驱动程序模块和Win32系统服务模块,它们和其它的模块在划分上有一些重迭。
l NK
NK透过NK.exe在系统运行,它是CE操作系统的真正核心,它主要包含以下6类:功能处理器排程、内存管理、异常处理、系统内的通讯机制、为其它部分提供核心应用程序例程 (routine)、为系统范围内的侦错提供的支持。
NK.exe的程序代码非常精简,始终以较高的优先级和处理器特权级别 (privilege mode) 执行,一般除了中断处理例程,系统内其它的执行绪不能中断kernel程序,并且在虚拟储存管理模式下,kernel程序是不被允许换出 (swap out) 的,它被存放在系统储存空间从0xC2000000起始的位置。 NK的程序代码位于[CEROOT]/PRIVATE/WINCEOS/COREOS/NK目录下。
l CoreDLL
CoreDLL在系统中具有举足轻重的地位,它区隔了应用程序和操作系统的其它模块,是使系统稳定的一个保护性屏障。它提供了两类功能:第一类是外部应用程序系统功能的代理;第二类则是类似字符串处理、随机数生成、时间计算等基本支持函式。前者是主要的功能,它负责系统API的管理和安装应用程序,系统应用程序的核心软件中断过程就发生在这里。这一个模块是透过CoreDLL.dll在运行,它是第一段被加载的系统共享程序代码。CoreDLL的程序代码位于[CEROOT]/PRIVATE/WINCEOS/COREOS/CORE目录下。
l 设备管理模块
这是Windows CE的设备管理核心,透过Device.exe来执行。它提供系统范围内基本的设备列表管理、随插即用管理、电源管理、I/O资源管理,并提供了装置驱动程序运作的基本机制。这一部分的程序代码位于[CEROOT]/PRIVATE/WINCEOS/COREOS/DEVICE目录下。详细信息请参考第6章。
l 数据储存模块
数据储存模块主要是提供系统基本的数据储存能力,其中包括对象储存以及档案系统,这些功能主要是透过filesys.exe来执行。关于这一部分的详细信息请参考第5章。数据储存模块并没有开放全部的原始程序代码,主要开放的原始程序代码部分位于[CEROOT]/PRIVATE/WINCEOS/COREOS/FSD这个目录以及[CEROOT]/PRIVATE/WINCEOS/COREOS/STORAGE这个目录下。
l 图形使用者接口模块
Windows CE透过这个模块提供的图形使用者接口,它提供几个主要的功能:基本的绘图引擎、窗口管理、接口的事件机制等。这个模块运行时为GWES.exe。详细的内容请参考第7章。这个模块的主要程序代码位于[CEROOT]/PRIVATE/WINCEOS/COREOS/GWE目录下,与数据储存一样,它的原始程序代码也只开放了一部分。
l 通讯模块
在整个Windows CE系统中,网络通讯模块是最为独立的一个部分,它是透过一系列的动态链接库来运作,这一部分因为牵涉到较多的Windows平台公用特性,所以原始程序代码开放的程度也最低。也正因为这个原因,本书并没有这一部分的详细分析。通信模块的结构如图2.2所示。可以找到的程序代码包括TAPI的一个实作、NDIS的一个实作版本 (pcx500),它们位于[CEROOT]/PRIVATE/WINCEOS/COMM目录下。
l OAL模块
这个模块没有确定的形态,主要包括和硬件相关的若干功能,例如处理器的专用支持程序代码、总线控制器的驱动、系统引导程序、系统初始化程序等等。一般来说OAL不具有可移植性。
l 驱动程序模块
驱动程序模块实际上并不是一个单独的软件实体,而是一个由驱动程序实体构成的集合,它包括很多组件,执行也比较复杂。它实际上是多个其它模块的底层,例如网络通讯模块 (参考图2.2) 的下层就是驱动层,NDIS实际上可以看作一个具体的类别驱动程序。此外它是分散在系统中的,有大量的驱动程序分布在OAL中,而系统服务和协议也可以看作是驱动程序,它们由不同的模块管理,例如services.exe和gwes.exe。
l Win32系统服务模块
Win32系统服务是Windows CE对应用程序提供的接口,多数公用的系统管理函式,例如,产生执行绪等,都是由NK负责。细心的读者应该已经发现了模块中的黑色虚线框,它表示系统实际运行时,这一模块某一部分内容被包含在NK.exe当中。这个模块也是有特殊性的,原因类似驱动模块,它实际上也包含多个模块的上层对外功能接口。在早期的CE版本中有一组基本的API函式管理集合,系统和使用者可以透过这组函式,将自行定义的接口注册到系统服务应用程序代理中,因为系统稳定性的缘故,目前这些函式只能在系统内部使用,例如和设备管理相关的Win32 API,就是藉由这组函式注册的。
2. 关连性剖析
各模块之间的关系大致可以用图2.12来表示。解释如下:
1) 图中实线箭头表示应用程序的依存关系,这种关系是一种tightly-coupled 的关系,被依赖的一方必须先于应用程序者存在。
2) 虚线箭头表示排程关系,这是一种loosely-coupled 的关系,当被依赖的内容不存在时 (还记得系统是可配置的吗? 当然可能会有不存在的部分),排程者并不会就此“罢工”。
3) 排程必须由某段程序发出的系统功能应用程序事件引发,这个排程完全是被动的服务。
4) 应用程序关系的发生是请求者主动发出的
5) 设备管理对驱动程序的依赖主要是在电源管理器的部分,电源管理器本身只是一个标准接口,它必须由OAL中的特定驱动程序来负责。
6) 驱动程序和OAL的一部分是重迭的,这在前面已经解释过了,此处不再赘述。
硬件 |
OAL |
CoreDLL |
NK |
驱动程序 |
网络通信 |
图形系统 |
数据储存 |
应用程序 |
设备管理 |
图2.12 模块关系示意图
2.4 系统机制
2.4.1 陷阱排程
陷阱排程为操作系统提供了意外事件的基本处理能力,这些意外事件大致上可以分为两类:中断和异常。一般来说,中断是异步事件,可能随时发生,与处理器正在执行的内容无关。中断主要由 I/O 设备、处理器频率 (CPU Clock) 或定时器产生,可以被启用或关闭;异常是同步事件,它是某一特定指令执行的结果。在相同条件下,异常可以重现。例如内存存取错误、排程指令以及分母为零 (divide by zero)。系统呼叫 (system call) 也被视作异常。软件和硬件都可以产生异常和中断。例如,总线错误异常是由硬件问题造成的,而分母为零则是由软件错误引起的。同样的,I/O设备可以产生中断,系统核心本身也可以发出软件中断。
意外事件 |
陷阱排程 |
中断处理 |
系统呼叫 |
通用保护 异常处理 |
分页错误 |
换页程序 |
结构化 异常处理 |
CoreDLL |
IST |
ISR |
图2.13 Windows CE 的陷阱排程
当陷阱处理程序被排程,系统会在记录系统状态的时候,暂时关闭中断处理。它会建立一个陷阱架构 (Trap Frame) 用来记录被中断执行绪的执行状态,以便在适当时机恢复执行绪的执行。陷阱架构通常是完整的执行绪描述表的子集。陷阱处理程序本身可以处理一些事件,但在大多数的情况下,陷阱处理程序判定发生的情况,并将控制权交给其它的模块。例如,当状况是设备中断产生时,系统核心会把控制权交给设备驱动程序提供给该中断设备的中断服务例程 (ISR) 以及中断服务执行绪 (IST)。如果状况是由排程系统服务产生的,陷阱处理程序会将控制权交给执行体中的系统服务代码。陷阱排程的架构如图2.13 所示。
2.4.2 处理程序间的通信机制
Windows CE提供的处理程序间的通讯 (IPC,Interprocess Communication) 机制比较简单实用,和桌上型计算机使用的操作系统相比,它没有提供诸如消息 (message)、端口 (port)、监督程序 (monitors) 之类的复杂通讯机制,而是提供了使用等待队列的基本通讯方式:临界区 (critical section)、事件 (event)、同步 (synchronization) 以及互斥器 (mutex),它们都被实作为系统对象。系统对象是由系统管理的资源实体,系统透过列表记录追踪它们的信息,当某个处理程序向系统请求一个系统对象的时候,系统将传回一个句柄加以标识,处理程序就可以透过这个句柄存取该对象。此外系统还提供了互斥的变量运算。对于嵌入式系统来说,这些方法简单实用、并且较不耗费系统成本。
通讯机制的一个基础,就是在某个对象上的等待队列。它就好像在银行领钱需要排队一样:银行的每个柜台办理不同的业务,当某个柜台正在为一位客户服务的时候,需要该服务的其它客户就需要排队,柜台就是系统对象,排队的客户就是要使用对象的处理程序或者执行绪、队伍就是等待队列。因为对系统对象的存取经常具有互斥性,所以当一个系统对象被多个执行绪共享时,系统就有可能产生等待队列,具体的实作可以参考第3章的内容。
1. 临界区 (critical section)
这是系统内部最常用的互斥方式,经常用于重要系统数据的修改。一般情况下,临界区对象用于保证一段程序代码执行的不间断性。一个临界区对象的使用被限制在某一个处理程序或者动态链接库当中,它不能被多个处理程序同时使用。
使用InitializeCriticalSection函数可以向系统取得一个临界区对象,当使用完毕之后,需要呼叫DeleteCriticalSection释放该资源。一段临界程序代码执行时,相关的临界区对象句柄必须是有效的,而这段程序代码需要以EnterCriticalSection或者TryEnterCriticalSection函数开始,而以LeaveCriticalSection结束。这样,系统可以保证当多个执行绪试图同时进入同一段临界程序代码时,只有一个会成功。
2. 事件 (event)
一个事件对象类似于一种特定的短消息,它用来通知某个执行绪系统发生了一个特定的事件或者告诉这个执行绪该做什么事了。例如随插即用管理器发现了一个新的设备,它会设置一个特定事件,系统就会触发和该事件相关联的执行绪,并告诉它系统增加了一个设备。
类似临界区对象,事件对象使用前也需要向系统要求资源句柄,在使用后则必须释放句柄,不同的是,系统藉由SetEvent或者PulseEvent设置一个事件,使用ResetEvent可以还原这个事件对象的状态。
3. 互斥器 (mutex)
互斥器的拥有者只能有一个,它的操作也相当简单,当使用CreateMutex申请资源成功时,执行绪就拥有了该资源的所有权,别的执行绪申请同样的资源就会进入等待队列,直到这个执行绪呼叫ReleaseMutex函数,释放资源为止。如果执行绪退出的时候没有呼叫ReleaseMutex,则这个资源会自动释放,等待队列上的第一个执行绪就会得到这个互斥器的所有权。
4. 号志 (semaphore)
号志和互斥器的基本原理是一样的,但是它允许特定数目的执行绪共享这个资源,获得和释放的函数分别为:CreateSemaphore和ReleaseSemaphore。
5. 互斥的变量运算
系统提供了8个函数用来改变某个共享变量的值,例如把某个共用计数变量的值增加1或者减少1。这些函数的共同特征是测试并改变这些变量的过程在处理程序中是不可中断的,可以视作不可分割的操作。
6. 内存共享
Windows CE中处理程序间的储存空间共享主要在两个层面:在逻辑储存层,主要藉由建立共享heap来处理程序之间达到内存共享的目的;而在虚拟内存管理的层次,系统则是藉由直接将不同的虚拟地址对应到同一实体地址来达到内存共享的目的。存取共享储存空间时,一般需要前面几种同步机制配合以保证程序执行的正确性。
应用程序代理 |
CoreDLL |
NK |
功能实现模块 |
载入 |
返回 |
注册接口 |
排程 |
执行 |
返回结果 |
图2.14 系统应用程序的客户端/伺服端代理模式
2.4.3 系统应用程序接口
1. 具有中间代理的客户端 / 伺服端结构
对DLL函数的呼叫,藉由程序加载器就可以达成,然而有大量的Win32 API是透过系统EXE程序来完成的。CoreDLL为这种情况提供了呼叫机制。在这种方式中,CoreDLL.dll充当两个主动对象 (两个独立处理程序或者执行绪) 之间的代理,而双方则构成伺服端和客户端的关系。应用程序者是客户端而系统功能实现者则是伺服端 (图2.14)。
呼叫的基本过程如下:
1) 使用者程序透过Windows SDK标头文件中的应用程序接口发出系统功能请求。
2) 应用程序接口透过宏转换为对CoreDLL中API应用程序接口的呼叫。
3) 引发系统软件中断,进入kernel,由排程机制捕获,转移到系统应用程序处理。
4) 系统确定负责该系统功能的函式。
5) 系统将该段程序代码附加到使用者空间,并切换到函式入口,恢复应用程序执行绪。
6) 系统功能得以在使用者处理程序空间执行并提供功能。
7) 呼叫结束,控制返回CoreDLL,并再次回到kernel。
8) 清除应用程序引起的的附加内容,结束处理、返回应用程序点的下一项指令。
9) 使用者处理程序得以继续。
图2.15 应用程序实例
2. 一个应用程序实例
图2.15是叫用 GetDC() 的过程示意图。其过程如下:
1) 使用者程序MyApp.exe透过应用程序接口发出对系统功能 GetDC() 的请求。
2) 应用程序接口透过宏转换为对 CoreDLL 中 API 应用程序接口的呼叫。
3) 引发系统软件中断,进入kernel,由排程机制捕获,转移到系统应用程序处理,亦即 GWES.exe。
4) 系统确定负责该系统功能的函式,GetDC()。
5) 系统将该段程序代码,GetDC(),附加到使用者 (MyApp.exe) 空间,并切换到函式入口,恢复应用程序执行绪。
6) GetDC() 得以在 MyApp.exe 的处理程序空间执行并提供功能。
2.4.4 可扩充韧体接口
可扩充韧体接口 (EFI, Extensible Firmware Interface) 是英特尔 (Intel) 公司为新一代计算机硬件架构、接口和服务提出的标准。它的主要目的是提供一套设定好的启动服务,这种启动服务在操作系统启动前具有与所有平台兼容的特性。
对于Windows CE的开发者来说,EFI 的出现意味着再也没有必要为个人计算机上Windows CE平台的初始化和加载系统kernel模块而特地去取得一份新的BIOS或者是MSDOS的授权。EFI的可扩充性提供了详细定义的机制来加载驱动程序和应用模块。EFI是随着原始码公布的,即使你的开发平台暂时不被EFI所支持,也可以藉由修改程序代码来让开发平台得以被EFI支持。
|
Windows CE kernel |
OEM 硬件 |
|
Windows CE kernel |
OEM 硬件 |
|
CE 开机加载程序 |
CE 开机加载程序 |
对象模块库 |
平台初始化 PCI 配置 显示 内存配置 除错控制台 储存媒体存取 |
EFI 开机载入服务 |
协定 处理 |
载入 设备 |
驱动 程序 |
图2.16 Windows CE开机加载程序架构,左图为不使用EFI,右图为使用
EFI系统架构
图2-16 显示使用EFI前后Windows CE的开机加载程序 (boot loader)。以前的Windows CE开机加载程序 (左图) 是从各个对象模块链接起来的服务所构成的一个整体组合,它们使用统一的API。使用这些模块库建立的开机加载程序随平台的不同而有极大的差异,并且对于每种新的或是修改过的平台都要进行升级或是重新开发。在很多情况下必须自己依照厂商提供的参考程序代码进行修改以适应那些暂时不被支持的平台。
右图则是显示一个采用分离模块的开机加载程序,它可以藉由EFI启动服务和模块库所提供的函式来下载Windows CE的系统kernel映像文件,执行平台检测和所有Windows CE kernel启动程序中关于平台配置的细节。驱动程序被定义成独立的协议接口,你可以为你的目标处理器使用 (导出) 一个已经存在的驱动程序或者从支持EFI标准的硬件厂商取得合适的驱动程序。
EFI规范定义了一个“字节代码虚拟机”,使驱动程序和应用程序同时支持多处理器。EFI字节代码编译器把 EFI 驱动程序从标准C程序代码编译成一种『虚拟程序代码』,虚拟程序代码透过特殊处理器上的核心加载服务驱动来解译执行。如此一来简化了多种不同平台和不同目标处理器上对驱动程序的开发和编译。
表2.2中部分 EFI 支持库提供了一些 EFI 应用程序和设备驱动模块执行时可用的函数。
表2.2 部分EFI支持库的函式
Shell服务 | 数学函数 |
平台初始化函数 Linked list支持宏 字符串函数 内部存储器支持函数 CRC支持函数 本文I/O函数 | Spin lock函数 Handle和协议支持函数 文件I/O函数 设备通路支持函数 Miscellaneous函数与宏 |
2.4.5 注册表
Windows CE的注册表用于储存关于应用程序、驱动程序、接口和其它配置信息,注册表具有层次化的组织结构,由若干个key 以及value 组成,类似档案系统;key相当于目录,而value相当于档案。整个CE .NET注册表形成一个有三个根节点的森林 (forest),每个根机码下储存一类配置信息。三个root key为:HKEY_LOCAL_MACHINE、HKEY_CURRENT_USER、HKEY_CLASSES_ROOT,分别储存硬件和驱动程序的配置信息、使用者配置信息、OLE和档案类型配置信息。
value就是注册表储存的数据,可以是字符串或者一个整数。Windows CE对注册表的value有一些限制:key或者value的名字最多255字符,数据大小最多4 KB,key嵌套层次最多16层。因而在使用注册表时应该尽量保持注册表的简洁性,以提升存取的效能。
系统提供全部的Win32 API注册表存取函式,使用者可以轻易的透过这些接口增加、删除、修改注册表的内容。
Windows CE支持两种类型的注册表:一种是基于对象储存的,另一种就是与Windows XP相同的注册表数据库结构——HIVE。这两种结构完全由嵌入式系统开发者处理,它们的区别对使用者和应用程序来说是不存在的。
1. 基于对象储存的结构
此种注册表的所有数据使用系统数据对象储存方式储存,这比较适合于使用电池的、内存不断电的硬件系统,它更加有效,并且更小。当内存需要断电时,OEM厂商应该提供专门的备份和恢复方法,以便在开机后可以恢复系统,这样效率会比较低。这种注册表适用于极少做冷启动 (cold boot) 的系统。
2. 基于HIVE的结构
HIVE注册表使用档案储存注册表数据,它没有系统内存断电时备份与恢复的问题,这可以使系统冷启动的速度加快。和Windows XP类似,这种注册表被分成两个部分:系统HIVE和使用者HIVE,当系统具有多使用者支持的时候,这种结构尤其适合。
2.4.6 Windows CE服务
Windows CE服务被看作一种驱动程序,它具有一般驱动程序的结构,但接口更加复杂,具有更强的容错能力,由Services.exe和Device.exe共同管理。从装置管理的角度来看,这种增强的驱动接口增加了系统的容错能力,使系统变得更加稳定。要使用这种特性,付出的代价就是Services.exe需要占用一个处理程序的Slot (最多32个,还记得吗?)。
1. 服务的自动加载
开启系统时,Services.exe根据注册表HKLM/Services key下的subkey启动服务。每个subkey均代表一个服务,其下的注册表value记录了该服务的配置信息,包括启动时的配置,Services.exe根据这些value决定如何启动这个服务。
2. 程序启动服务
系统提供了一个函式用以启动一个未运行的服务:ActivateService。它需要服务名作为参数,这个函式使得Services.exe根据对应的HKLM/Services subkey下的value启动该服务。
3. 注册服务
透过RegisterService来注册一个服务,它向Services.exe请求启动一个有参数的服务。这个函式类似于RegisterDevice,不同的是后者由Devices.exe控制运行。
4. 停止服务
DeregisterService负责一个服务的注销和停止。
5. 控制服务
一个服务 (驱动) 需要实作档案串流接口,它们的使用跟对档案的操作并没有太大的差别,例如,可以用CreateFile来打开一个服务句柄。
最后
以上就是危机饼干为你收集整理的WinCE 编程实验(第二章 Windows CE系统结构) 的全部内容,希望文章能够帮你解决WinCE 编程实验(第二章 Windows CE系统结构) 所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复