Windows CE内存管理

来源:互联网 发布:淘宝抢购验证码 编辑:程序博客网 时间:2024/06/04 18:48

作者:michaelcao1980

转自:http://blog.csdn.net/michaelcao1980/article/details/8240079


Windows CE 有着很多不同内存的分配方法。

picture 6

       上图显示了所有的内存分配方式,在我刚开始学习的时候,也不是很明白为什么有着这么多种的分配方式。其实就一句话:越往下面的内存分配方式效率越高,但是应用的复杂度也就越高。

 

虚拟内存分配可以用以下方法来实现:

分配函数:   

  LPVOID VirtualAlloc(LPVOID, DWORD, DWORD,DWORD)

LPVOID VirtualAlloc( LPVOID lpAddress, DWORD dwSize, DWORD flAllocationType, DWORD flProtect);

对于用户进程虚拟空间当中的每个page都有3种状态:

a,free:处于此种状态的page,既没有reserved也没有commit,也就是说它还没有跟物理内存做对应,所有应用程序还不能访问。

b,reserved:处于此种状态的页说明已经被该进程预留了,不能再做其它应用了。如果在该进程当中调用如new(), malloc()等函数申请内存空间,返回的地址不会再reserved空间范围之内,因为它已经被预定了。但是目前它仍然不能被访问,因为还没有和物理内存对应起来。

c,committed:经过committed之后的虚拟地址空间,已经与物理地址做了映射,就能够被进程访问了。

当进程终止的时候该提交的内存页被释放,也就是说该物理内存可以被其它进程使用了,当然我们不应该依靠进程终止来释放物理内存空间,而是应该使用virtualFree()手动释放该物理空间,避免因操作不当导致内存泄露。

释放函数:

  LPVOID VirtualFree(LPVOID, DWORD, DWORD)

  

改变和查询访问权限函数:

  LPVOID VirtualProtect(LPVOID, DWORD, DWORD,DWORD)

 

这3个函数具体的参数可以查看MSDN,在这里就不详细介绍了。在使用这3个函数的时候我们需要注意一些问题,用个书上的例子来解释:

for(i = 0; i < 512; i++)

{

        pMem[i] = VirtualAlloc(NULL, PAGESIZE,        

                                               MEM_RESERVE | MEM_COMMIT,                       

                                                PAGE_RDWRITE);

}

 

也许在XP下我们写这种程序也成习惯了,但是这是在Windows CE中,这里我们就需要注意一些问题了:

1.保留的虚拟内存是按照64KB对齐的。

2.提交的虚拟内存是按照页面来对齐的。

大家也许就已经明白过来了,如果我们这样去申请内存,在系统自动内存对齐的情况下我们是会浪费非常多的内存的,在5.0中测试这个程序,分配会失败,在6.0中分配成功,大家可以去试验一下。那么我们正确的做法应该是先保留一个大的内存块,然后再需要用的时候再提交一次。

pMemBase = VirtualAlloc (NULL, PAGESIZE,    MEM_RESERVE,                       

                                             PAGE_REDWRITE);

 

for(i = 0; i < 512; i++)

{

   pMem[i] = VirtualAlloc (pMemBase + (i * PAGESIZE),                     
                                            PAGESIZE,  MEM_COMMIT,                    

                                            PAGE_REDWRITE);

}

通过这些学习也给了我们一定的启示:

CE 5.0的32*32的局限:

        1.尽可能少使用多进程。

        2.可以多利用多线程。

        3.使用内存映射文件区域申请大内存

 

     虚拟内存分配的64KB对齐:

        1.尽可能按照64KB边界申请虚拟地址空间。

        2.一次申请,多次提交。

        3.使用更上层的动态内存分配函数。

        4.合并小的DLL为64KB边界。

堆和栈的内容就不在这里介绍了。


总结

我们已经讨论了不同的内存类型,现在来讨论如何充分利用各种内存类型。

 

   1.对于大的内存块,最好是直接分配虚拟内存。

 

   2.本地堆使用便利,但是需要注意内存碎片。

 

   3.独立堆的优点是当你不使用时可以直接销毁它,从而把内存碎片消灭在萌芽状态。

 

   4.静态数据区域是放一两个缓冲区的好地方,因为页面总是要被分配的。

 

   5.栈使用简单,但是栈的大小只有64KB。