越是相近的东西,越是容易混淆;反倒是不同的特征,容易描述清楚。既如此,我就从简到难,先来讲讲内存布局的区别吧。
首先是经典的CE 5内存布局:
rel="File-List" href="file:///C:%5CDOCUME%7E1%5CADMINI%7E1%5CLOCALS%7E1%5CTemp%5Cmsohtml1%5C04%5Cclip_filelist.xml">
嗯,的确是非常经典的内存映射方式。任何一个ARM程序员,即便没有接触过WinCE,也很容易理解这张图。它简直就是为ARM度身订制的!
总共4GB的虚拟空间,最低的1GB被分割成32个槽(Slot), 每个槽容纳一个进程,因此,每个进程可用的最大虚拟空间是32MB(当然,这个32MB的上限很像NBA的工资帽,只要动些脑筋,找些特例,总可以超过这个界限)。Slot 0对应当前进程,Slot 1中没有进程,CE 5把系统预制的dll放在这个区域。从Slot 2开始,每个Slot被唯一地映射到一个进程,一般来讲,按照启动顺序,依次是filesys.exe, device.exe, gwes.exe等等。需要注意的是,CE 5是很典型的微内核结构,因此,各种系统调用被区分成不同的服务,由各个应用程序提供。比如文件系统的调用,就是由filesys.exe提供。虽然这些程序提供的是系统服务,但是从内核的角度来讲,称它们为应用程序是十分恰当的,因为他们的的确确运行在用户态中。
1GB到2GB的内存是共享的。2MB以上的内存块分配,内存映射文件等,都在这里发生。
2GB到3GB的内存是静态映射的。这意味着,在任何时候,这段内存映射都是不变的。其中较低的一半地址,0x80000000 – 0x9FFFFFFF,是Cacheable;而另一半,则是Uncacheable的。定制CE的开发人员,需要创建一个数组,指明Cacheable的地址,是如何映射到系统的物理内存空间的,并把这个数组传递给CE内核。内核会自动创建Uncacheable的地址,映射方式恰好等于前者加上0x20000000。
0xC0000000以上的空间完全被内核代码和数据结构使用。虽然微软把内核称为一个进程,而且也确实把它放在进程数组的第0个元素,但说实话,我还是不愿意把内核理解为一个进程。在内核地址中,比较有趣的是一些非常非常高的地址,大约是0xFFFD0000以上的地址,这里放置了中断向量、页表等关键的结构,很值得仔细探讨一下。
好了,这就是CE 5的大致内存布局了。下次和CE 6对比一下!