WinCE下申请大容量物理内存(转)

news/2024/7/20 14:07:02 标签: 内存管理, c/c++, 操作系统
申请大容量的物理内存看起来不是难事。这里的大容量是指几十MB甚至更多的物理内存。对于C++程序员来说可能平时习惯了使用“new”操作符来实现。我也是这样。使用“new”非常简单,申请之后只需判断返回的指针是否是空即可。在其它的Windows操作系统上的确不需要在申请大容量物理内存上过多考虑。但是在Windows CE上就不同了。如果只用“new”就能搞定,那就太省事了。

  不知道Windows CE下软件开发者是否遇到过这种情况,如果使用“new”申请超过30MB的物理内存,那么返回的一定是空(NULL),甚至程序会死锁无法响应。这其实不奇怪。在《Windows CE下进程、线程和内存管理》的系列文章中我早有所言,Windows CE下每个进程占有32MB的地址空间,虽然Slot 1槽存放所有的非XIP DLL,但是我们不可能占用Slot 1槽。32MB地址空间减去必要的代码段、静态数据段、默认堆和默认栈之后,所剩的地址空间少于32MB。即使程序什么都不做也无法满足超过30MB的地址空间的申请需求。所以返回为空非常正常。好在Windows CE下运行的大多数软件不需要那么多的物理内存。

  感觉微软的技术不是支持到很远的将来,而是得过且过,只要满足目前的和不远的将来的需求就行。拿Platform Builder来说,IMGRAM64环境变量用于支持64MB物理内存。可是没有IMGRAM128或者IMGRAM256甚至IMGRAM512。可能是当时绝大多数基于Windows CE的产品都没有超过64MB物理内存。现在要支持超过64MB物理内存就必须做一些修改操作。再如现在说的用“new”分配物理内存,也只是限制在32MB以内。如果想new多少就new多少,那多爽!

  “new”不行是因为地址空间不够,那我们可以采用虚拟内存分配,然后提交物理内存这种办法。理论上是这样,但是实际上还是不行。举例如下:

LPVOID g_Address1, g_Address2;

g_Address1 = VirtualAlloc(0, 32 * 1024 * 1024, MEM_RESERVE, PAGE_NOACCESS);
g_Address2 = VirtualAlloc(g_Address1, 32 * 1024 * 1024, MEM_COMMIT, PAGE_READWRITE);


  上面这段代码中第一个语句是申请32MB的虚拟地址空间,函数返回一个地址说明申请是成功的。注意这个地址一定处于0x4200 0000以上(具体参见我的专栏中《Windows CE下进程、线程和内存管理(三)》)。第二个语句是提交物理内存,容量为32MB。这个函数返回NULL,说明申请物理内存不成功。如果申请10MB、20MB的还可以。

  希望再一次破灭。最后的办法就是内存映射文件了。在Windows CE的帮助文档中只提到了内存映射文件可以用来申请虚拟地址空间。可以试一试。结果证明用内存映射文件来申请大容量物理内存是可行的。内存映射文件用于多个进程共享数据时,创建内存映射的函数的第一个参数必须设置为INVALID_HANDLE_VALUE,表示在物理内存中创建。利用这个特点我们可以申请超过32MB的物理内存。具体能够申请的大小由剩余的物理内存决定。例子如下:

#define MAXLEN (64*1024*1024)
HANDLE hFile;
hFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, MAXLEN, NULL);
if(hFile == NULL)
{
///创建文件映射对象失败
return;
}
LPVOID lpAddress;
lpAddress = MapViewOfFile(hFile, FILE_MAP_WRITE|FILE_MAP_READ, 0, 0, MAXLEN);
if(lpAddress == NULL)
{
///创建文件视图失败
return;
}


  上述的函数如果都成功了,你就可以使用物理内存了。虚拟内存的首地址是lpAddress。使用完了别忘了调用函数UnmapViewOfFile(lpAddress); 和CloseHandle(hFile);


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/10294527/viewspace-126742/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/10294527/viewspace-126742/


http://www.niftyadmin.cn/n/1438934.html

相关文章

Linux中变量,basename,$#,$@,$0,$1,$2,$*,$$,$? [-eq] [-ne] [-gt] [-lt] [ge] [le]的含义

$# 是传给脚本的参数个数 $0 是脚本本身的名字 $1 是传递给该shell脚本的第一个参数 $2 是传递给该shell脚本的第二个参数 $ 是传给脚本的所有参数的列表 $* 是以一个单字符串显示所有向脚本传递的参数,与位置变量不同,参数可超过9个 $$ 是脚本运行的当前…

spring框架篇(一)-------spring简介与配置文件使用控制反转事例

spring简介 Spring 是一个开源框架,中文意思就是春天,也许是作者想让自己的这个框架给Java开发人员带来春天吧。其官方网站是 https://spring.io/ ,可以在官方网站下载到完整的类库,源代码以及文档。spring是一个高度灵活的轻量级…

游戏引擎剖析(五)(转)

第5部分: 物理,运动,效果世界建造  常常在建立一个含有任何3D成分的游戏时,你最终要试图建立一个将会在里面产生游戏动作的3D环境。 不知怎么的游戏开发者提供了一个建立这种环境的方,它容易修改,有效率,…

ACCESS集锦(转)

1、使窗体或报表的文本框随文字的多少自动加大或缩小:文本框属性“可以扩大”2、控制某字段只能填写某些内容:也许你想让使用程序的人只能在某个字段里a,那么你就得控制他不难让他填b。具体表达式为Instr("abc",[A]&…

微信开发SDK|微信sdk使用教程--手机客户端微信下线通知服务端

微信开发SDK|微信sdk使用教程--手机客户端微信下线通知服务端 case WeChatOfflineNotice: {// 手机客户端微信下线通知 log.debug("socket:msgtypeWeChatOfflineNotice"); weChatOfflineNoticeHandler.handleMsg(ctx, msgVo); break; } package com.jubotech.framewo…

图片在网站中的问题

1.图片在自适应的时候注意: 在大屏轮播的时候把图片的宽度变成100%就行这个图片; 在响应式的网站上的一个1920的图片和 768*448的图片两张图片互相变化 .swiper-wrapper .header-bottem-cen1 img.big { display: none;}.swiper-wrapper .header-bottem-c…

解析GPRS 协议栈功能(转)

张冰涛, 现任广州金鹏集团工程技术中心技术支持部经理兼高级系统工程师。1998年4月毕业于东北大学连轧自动化国家重点实验室,并获工学硕士学位。同年加入金鹏集团有限公司,主要负责GSM、GPRS、CDMA的售前、售后技术支持工作和系统网络优化工作…

数据库中加条件判断来决定显示的数值(转)

数据库中加条件判断来决定显示的数值:SELECT jxc_yj_xzwz.clmc AS 物资名称, jxc_yj_xzwz.ggxh AS 规格型号, CAST(jxc_yj_xzwz.sl AS int) AS 数量, ISNULL(scdwbmk.dwmc, ) AS 所属部门, CASE jxc_yj_xzwz.syqk WHEN 0 THEN 未使用 ELSE 使用 END AS 使用情况, SU…