5.4 Hello China内存管理模型
5.4.1 Hello China的内存管理模型
在Intel 32位CPU上实现目前版本的Hello China采用的是最简单的平展模式,即数据段、代码段和堆栈段相互重叠,覆盖CPU的整个线性地址空间。下面的汇编代码是代码断、数据段和堆栈段的段描述符的定义:
gl_sysgdt: ;;The start address of GDT. ;;In order to load the mini-kernal,the sys- ;;tem loader program,such as sysldrd.com(f- ;;or DOS) or sysldrb(for DISK),have initia- ;;lized the GDT,and make the code segment ;;and data segment can address the whole 32 ;;bits linear address. ;;After the mini-kernal loaded,the control ;;transform to the OS kernal,so the kernal ;;will initialize the GDT again,this initi- ;;alization will make the GDT much proper. gl_gdt_null dd 0 ;;The first entry of GDT must be NULL. dd 0 gl_gdt_syscode ;;The system code segment's GDT entry. dw 0xFFFF dw 0x0000 db 0x00 dw 0xCF9B db 0x00 gl_gdt_sysdata ;;The system data segment's GDT entry. dw 0xFFFF dw 0x0000 db 0x00 dw 0xCF93 db 0x00 gl_gdt_sysstack ;;The system stack segment's GDT entry. dw 0xFFFF dw 0x0000 ;;The stack's base address is ;;0x01000000 db 0x00 dw 0xCF93 db 0x00
结合IA32 CPU的段描述符的定义,可以看出,目前Hello China实现的段属性如表5-4所示。
表5-4 Hello China的段属性
这样的实现实际上是一种最简单、最通用的实现,相当于忽略了IA32的段机制。在嵌入式开发中,这种情况最为常见,因此,按照这种模型实现的操作系统可移植性要高一些。另外,这种模型符合C语言的内存管理模型,因为按照C语言的标准,一个指针应该能够寻址地址空间中的任何对象,若采用不重合的段模型则可能会出现问题。比如有下列两个函数:
VOID Function1(DWORD* lpdwResult,DWORD dw1,DWORD dw2) { *lpdwResult=dw1+dw2; } VOID Function2() { DWORD dw1=100; DWORD dw2=200; DWORD dwResult=0; Function1(&dwResult,dw1,dw2); }
在第二个函数中,dwResult的位置实际上是在堆栈段里面的,这样在调用第一个函数(Function1)的时候,传递过去的参数(&dwResult)实际上是堆栈段的一个地址(偏移)。但是在第一个函数中引用lpdwResult时,缺省情况下是按照数据段内的地址来引用的。这样若堆栈段和数据段不重叠,就不会引用到正确的位置,导致执行结果不正确,严重的时候,还会引起系统崩溃。之所以产生这个问题,是因为一般的编译器在传递指针参数时只传递段偏移部分,而不传递段选择子。
在当前的实现中,Hello China没有实现进程,只实现了线程,而且实现时,所用的线程和操作系统核心代码以及数据共享同一线性空间。这样的实现方式,也是大多数嵌入式操作系统实现的方式。这种实现方式效率会比进程模型高,因为在线程切换的时候,没有必要切换段寄存器(这会引起整个CPU Cache的刷新),只需要完成堆栈、通用寄存器的切换即可。但也有一个弊端,就是保护功能稍微弱一些,一个线程的崩溃可能会导致整个系统的崩溃。
虽然没有充分采用IA32 CPU的分段机制,但目前Hello China的实现却充分采用了CPU的分页机制来完成内存保护功能。通过分页功能可以很容易地把线性地址空间内的内存地址,映射到物理内存当中,而且还可以实现按需内存分配功能,保证了内存资源的充分利用。
下面,我们首先对操作系统启动后的内存布局进行描述,然后对系统中的下列两个物理内存区域进行描述:
(1)核心内存池,供操作系统和设备驱动程序使用,进一步分成4KB区(以4KB为单位进行分配)和任意尺寸区(以任何尺寸进行分配);
(2)分页管理区,供应用程序使用,以分页的方式进行管理。
上述两个区域都是物理内存区域,在完成上面两个区域的管理方式的描述后,将详细介绍Hello China的虚拟内存实现方法。在当前版本中,虚拟内存的实现是建立在CPU的分页机制上的。