问系统高手, 内存问题?

yycall   2007-11-5 12:41 楼主
请问高手中的高手来指点一下,有以下两个问题困惑几天.

环境: VS2005 smart + PPC 2003 SE模拟器下开发运行.

一) 目前自己来负责做内存管理模块, 局部策略实现最终需要和系统打交道, 比如在申请虚拟地址空间时,
用到了virtualalloc函数,不解的时,调用virtualalloc时候,参看题为,
"Windows CE 进程、线程和内存管理(三)"一文, 0x4200 0000到0x7FFF FFFF,

我也不知道,怎么应用, 查看MSDN,可以第一参数可以默认为0, 不指定地址范围.

如果,
WORD aMaxSizes = 22*1024*1024;
void *Addr = VirtualAlloc((LPVOID)0x42000000, aMaxSizes, MEM_RESERVE, PAGE_READWRITE);

Addr = 0x00000000?  

如果,
m_pBaseAddr = VirtualAlloc((LPVOID)0, aMaxSizes, MEM_RESERVE, PAGE_READWRITE);
Addr = 0x00150000, 不是落在0x4200 0000到0x7FFF FFFF之间的?
此时取得DWORD nErr = GetLastError();
      error code 是126 :  找不到指定的模块

请问,上面的用法有什么问题?
    如何真正保证申请的虚拟地址空间落在0x4200 0000到0x7FFF FFFF这个大的范围内.


二) 问题是如何查看和监视模拟器PPC 下的内存状况?
   什么工具和方法?


  谢谢高手中的高手关注一下. 不知道查什么好, MSDN也是通而无用.

回复评论 (19)

第一问题没看明白。
第二个问题不知道你需要查看哪些状况?remote工具可以查看内存的一些状况,但不知道是不是你需要的。
点赞  2007-11-5 16:12
谢谢楼上的回复.
关于第一个问题,就是VirtualAlloc的用法,看了一个周,云里雾里,说到底是不知道怎么用?

第2个问题,是想找个WinCE内存监视工具,可以查看当前程序内存的大小,以及当前可用内存的大小和内存使用率等,
VS 2005怎么没Remote system information 这个了.


点赞  2007-11-5 17:03
没有人说VirtualAlloc分配出来的空间就是落在0x4200   0000到0x7FFF   FFFF之间的!!

从0x00000000 到 0x41FFFFFF 是所有应用程序共同使用的, 共分33个槽, 每个槽占用32M. 只有当某些进程32M地址空间不能够满足的时候,才调用0x4200   0000到0x7FFF   FFFF

所以 m_pBaseAddr   =   VirtualAlloc((LPVOID)0,   aMaxSizes,   MEM_RESERVE,   PAGE_READWRITE); //应该你的进程没有用完32M吧
Addr   =   0x00150000,   不是落在0x4200   0000到0x7FFF   FFFF之间的?   //所以这个问题也很清楚了.

void   *Addr   =   VirtualAlloc((LPVOID)0x42000000,   aMaxSizes,   MEM_RESERVE,   PAGE_READWRITE); //至于这个等于Null的话,你可以查看Getlasterror 获得一些信息. 我这里没法试

还有一种说法可以参考:
在CE5.0之前,使用VirtualAlloc获得的虚拟地址空间分为两种情形:
(1)大小在2MB以下时,位于调用进程的虚拟空间中;
(2)大小大于2MB时,位于用户态的共享地址空间内(0x42000000-0x7E000000 )
点赞  2007-11-6 10:33
呵呵,vs2005里没有,你还可以回去用evc的啊

virtual没用过了。
点赞  2007-11-6 11:02
自己研究一下,还需要大家来关注,辛苦了...
一)对问题一,
VCKBASE 的文章http://www.vckbase.com/document/viewdoc/?id=1156

和 MS mvp写的Windows CE .NET 高级内存管理 一文,

之后有所了解关于CE虚拟内存布局和应用程序虚拟内存的布局情况,

不过请问大家有谁知道,为什么
      当请求的一块保留区
        VOID*P2  = VirtualAlloc((void *)0x46000000, 5*1024*1024, MEM_RESERVE, PAGE_READWRITE);
        DWORD nErrcode = GetLastError();
nErrcode =8 , 存储空间不足,无法处理此命令。 到底是怎么回事情?
我使用        MEMORYSTATUS MemStatus;
        GlobalMemoryStatus(&MemStatus);
        查看可用的物理内存和虚拟内存都超过5M?

二)对问题二,用GlobalMemoryStatus和GetSystemInfo函数。
点赞  2007-11-7 09:48
建议你去看看我的blog  
http://blog.eeworld.net/nbcool

你说的那篇 MSDN上的 Windows CE.NET 高级内存管理,并不完整,只能做为补充资料。

1.如果虚拟地址不连续,怎么给你分配5M?

2.研究内存问题,工具和方法很多,不必局限在某个API。
点赞  2007-11-7 10:43
关于virtualalloc方面的问题, 还有很多实际的疑惑.
1. 我们用的VS2005 PPC 2003 是模拟器的环境相当于WINCE什么版本?
2. CE4.0和5.0虚拟内存布局方面有什么同异?
3. virtualalloc分配的结果总是与预料不同?
4. 模拟器下内存大小怎么样调节?
点赞  2007-11-7 11:00
载舟之水,谢谢你了,我先看看, 有时间希望能交流一下.
做开发做了四五年对靠底层的东西还是缺乏实际的经验,呵呵.
点赞  2007-11-7 11:06
1. PPC2003有第一版和第二版PPC2003 SE,现在一般用的是第二版本,内核是WinCE.net 4.2
2. CE4.0内存管理和 CE.net 4.2 CE5.0 是有些小差异的,后两者是相同的。
3. 正确的使用方法能得到正确的结果,如果每次都和预料不一样,那不成了彩票了?
4. PPC 2003 模拟器能调节应用程序空间和对象存储空间的分配,PPC 5.0之后,已经统一了这两块空间,不再提供调节。
点赞  2007-11-7 11:09
载舟之水, 很感谢你的再一次关注,
我有点两点疑问:
一)
PPC2003   SE VS2005建个工程,
VOID* addr  = VirtualAlloc((void*)0x42000000, 10, MEM_RESERVE,  PAGE_READWRITE);
DWORD nErrcode = GetLastError();
发现addr是0, 是关于nErrcode   =8, 存储空间不足,无法处理此命令? 只申请10个BYTE的虚拟空间.
存在什么问题呢?

补充说一下我对VirtualAlloc的用法理解, 理解错误或片面,还望多多指教
如果第一个参数是0, 那么系统来确定基地址, 但在0x00010000--0X2000000 32M的虚拟空间内,当然系统本地heap, stack, 静态数据段和代码等预留的除外;

如果第一个参数非0, 也就是当需求增大扩充虚拟空间. 这个时候需要指定的空间,  0x42000000--0x7FFFFFFF之间,

对第二个参数, 建议是PAGE_SIZE自动对齐,因为会导致重复覆盖的情况, http://www.cnblogs.com/walzer/archive/2007/01/22/626562.html有文说明验证过.

二) PPC   2003   模拟器能调节应用程序空间和对象存储空间的分配,不知何处?
点赞  2007-11-7 14:26
留下这两个问题.
VOID*addr  = VirtualAlloc((void *)0x46000000, 64*1024, MEM_RESERVE,  PAGE_READWRITE);
DWORD nErrcode2 = GetLastError();
// addr =0, nErrcode2 =8  存储空间不足,无法处理此命令

VOID*P  = VirtualAlloc((LPVOID*)0, 5*1024*1024, MEM_RESERVE, PAGE_READWRITE);
VOID*addr  = VirtualAlloc((LPVOID*)P, 1*1024*1024, MEM_RESERVE, PAGE_READWRITE);
DWORD nErrcode2 = GetLastError();
// addr =0, nErrcode2 =87 参数不正确
点赞  2007-11-7 16:10
刚才笔误,是VOID*, 不过结果怎么都是不对.
点赞  2007-11-7 16:20
我建议你还是反复仔细地研读正确的资料,比如MSDN,以及在我的blog中的译文,另外,多参考 Microsoft的 sample code。

你的代码中问题很多,我无法一一指出,只能提醒一下,

1.你在0x46000000 分配时,并没有先去查询是否有空间可供分配,如果只有63*1024,那自然会报告存储空间不足。
2.参数确实错了。
点赞  2007-11-7 17:57
VOID*addr     =   VirtualAlloc((LPVOID*)P,   1*1024*1024,   MEM_RESERVE,   PAGE_READWRITE);
//在付林林编辑的一本PB书里,说到到传递的地址不为0时,返回值永远都是不正确的.  但是书里没有说明原因, 也许这就是wince的特点?!
//可是msdn却没有说明这一点.

这些问题应该不是存不存在这么大空间的问题.
点赞  2007-11-8 08:16
摘自原文:
在实践中发现给参数1传递非0值均不成功,即使传递0给参数1让内核自动查找空闲地址空间,得到的返回值赋给参数1再次调用此函数(之前已经释放第一次申请的地址空间)也不成功.  所以在调用 VirtualAlloc函数时尽量传递0给参数1.如果申请的虚拟空间超过一定范围,那么内核将在0x42000000 到 0x7FFFFFFF 之间分配地址空间.



//另外,如果楼主仅仅是研究这一现象也罢了,如果实际应用中 还是建议使用内存映射文件技术 来解决大物理空间问题.
点赞  2007-11-8 08:26
是的,第二参数的确错了,后来我发现,针对非0的情况,用法是有点武断,呵呵,谢谢各位,载舟之水和KevinCEC ,谢谢你们你们的回复,载舟之水的翻译MS MVP -Douglas Boling的文章不错, 技术坚定和视野开阔,绝对是中华武林高手.
点赞  2007-11-8 09:45
补充一下,参数错是因为,
        VOID*P  = VirtualAlloc((LPVOID)0, 5*1024*1024, MEM_RESERVE, PAGE_READWRITE);
        VOID*Q  = VirtualAlloc((int*)P+5*1024*1024, 1*1024*1024, MEM_RESERVE, PAGE_READWRITE);
这个时候Q可获取合理的虚拟地址了. 准备就给大家分了, 我嫌给分太少, 人生道路朋友才珍贵. 呵呵!
点赞  2007-11-8 09:53
另外说一下,付林林并不是内存方面的专家,他对内存问题也是一知半解,很久以前我就指出过他文章的多处问题。我前面说的看正确的资料,一定是要以MSDN上的文章为准的,尽管MSDN也有不少错误,但是还是比较可信的。MS MVP Douglas   Boling被微软誉为对WINCE理解最完美的人之一,所以他的文章也具有参考价值。
点赞  2007-11-8 12:19

既然今天来eeworld(有几年没来了),碰到高手就说上几句。我不是什么高手。相对来说,技术的深处还研究不够。
目前在移植和开发某平台引擎,里面有块就要用到内存管理的部分。04年过sa,每天仍坚持学习两三个小时,主要研究
设计模式和架构,更早的时候也是学技术COM,研究ATL源码,后来从分布式架构到目前的嵌入式领域通信架构、应用,
直到OS 内核的架构,我也就不再探究了,其实倒有些兴趣。我一直看书,都在致力于将花拳绣腿的模型经过验证变成可执行的模型,却可能又偏偏有些忽视了实现本身的一些东西,如算法和计算机知识等问题。不过,我更重要是在修养自己的品格。讲一个我们中国人可能容易忽视的品格吧, 敢于质疑和创新, 是科学发展的最核心的力量. 见笑的地方,来eeworld,工作紧迫,思维和测试代码未经整理。呵呵,幸会,中国有载舟之水,所言有理,非常谢谢你的回复!
点赞  2007-11-8 13:24
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复