http://www.cnblogs.com/eaglet/archive/2008/11/06/1328061.html
让.Net 应用程序突破2G的内存访问限制
Author: Eaglet
32位Windows操作系统下单个进程的用户模式内存访问的限制是2G,如果在boot.ini中设置了/3G开关,则最大为3G,超过3G将无法访问。由于Hubble.net 项目是一个数据库系统,必须要考虑使用大内存缓存数据的问题,于是最近对这个问题进行了一些研究。其实这块的技术是现成的,32位操作系统下只有通过AWE的方式来扩展内存。这块的文章也很多,但很少有.net 下如何使用的实例,我做了一个类似MemoryStream的封装,可以让.Net程序员轻松操作AWE内存,从而使其程序轻松突破2G内存的限制。
在开始这篇文章之前,我们还是先来了解一下AWE.
AWE (Address Windowing Extensions)是 Windows 的内存管理功能的一组扩展,它使应用程序能够使用的内存量超过通过标准 32 位寻址可使用的 2-3 GB 内存。AWE 允许应用程序获取物理内存,然后将非分页内存的视图动态映射到 32 位地址空间。虽然 32 位地址空间限制为 4 GB,但是非分页内存却可以远远大于 4 GB。这使需要大量内存的应用程序(如大型数据库系统)能使用的内存量远远大于 32 位地址空间所支持的内存量。
如上图所示AWE 实际上就是将用户模式下的32位内存地址映射到用户需要访问的物理内存上去。不同操作系统运行被映射的物理内存大小是不一样的。
Vista, XP 和 Windows 2003 标准版 最多可以映射 4G 内存。
Windows 2003 企业版的限制是32G (要使用超过4G的内存必须打开 /PAE 开关)
Windows 2003 数据中心版本限制是64G (要使用超过4G的内存必须打开 /PAE 开关)
由于被映射的物理内存为不分页内存,无法进行页保护,为了保证内存使用的安全,防止其他进程越界访问,AWE 在映射这些内存之前必须将这些内存锁定,即只有锁定这块内存的进程可以访问这块内存,其它进程无法访问。这里就产生了一个有趣的现象,我们可以在windows 下像实时操作系统那样操作物理内存,而不用担心操作系统进行页交换时对系统实时性的影响。虽然不采用AWE,也可以通过VirtualLock API函数来锁定物理内存,但这个函数在一个进程中最多可以锁定30个页面,以一个页大小4096来计算,最多可以锁定30*4094字节的内存。当然这是默认设置,你也可以通过调整工作 WorkingSet 来调整。看来AWE对于那些实时性比较高的应用,比如游戏,动画,通讯等还确实是一个福音。
由于需要锁定物理内存,所以运行AWE功能的程序,必须要具备锁定内存的权限,系统管理员帐号是没有这个权限的,只有 System帐号有这个权限。当然你也可以在本地安全设置中指定某个帐号拥有这个权限。方法如下:
gpedit.msc ->Windows Settings->Security Settings->Local Policies->User Rights Assignment->Lock pages in memory
谈完锁定内存的问题,我们再看看上面那个图,我们会发现虽然AWE允许访问最多64G的内存,但这64G内存是被AWE映射到一个32位的用户模式下的内存地址中去的,也就是说通常情况下,我们最多可以同时访问64G内存中的2G内存 (如果配置了/3G开关,可以同时访问最多16G内存中的3G内存),如果要访问整个64G的内存,我们需要将一些不访问的内存取消映射,这样可以空出足够的用户模式下的虚拟内存地址来访问我们需要访问的内存。因此我封装的类中添加了Map和UnMap两个方法,让调用者可以根据实际情况来决定映射和去映射。2G的32位虚拟内存地址对于我们来是是如此的宝贵,调用者在贪婪的消耗大量内存时一定要注意节约这个资源。
谈完这些东西,下面让我们结合代码来看看在.Net 下如何来操作AWE 内存吧。
为了方便.Net 程序员访问AWE内存,我封装了一个AweStream类,这个类继承自Stream类。.Net程序员可以像操作普通的MemoryStream流那样操作AWE内存。同时我还为那些对效率要求非常苛刻的调用者提供了一个通过指针访问AWE内存的方法。
调用示例如下:注意必须在构造函数中指明申请的AWE内存的大小。
我在 6G内存 windows 2003 企业版的环境中做了测试,申请内存到5G以上没有任何问题。
下面再看看如何来申请AWE内存
下面的AweStream构造函数完成了对AWE内存的申请过程。
整个申请过程分为下面几步
1、为当前进程申请锁定内存的权限(注意 调用进程的帐号必须具备锁定内存的权限,否则这一步会失败)
2、就是需要申请的页面数量
3、通过 AllocateUserPhysicalPages API 申请AWE内存
AWE内存申请完毕后并不能被立即访问到,我们必须将其映射到32位内存地址中才可以访问。
下面是内存映射的代码:
也很简单:
首先先通过VirtualAlloc函数申请一块32位虚拟内存区域
然后通过 MapUserPhysicalPages API 函数将AWE内存映射到这个虚拟内存地址区域。
<!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->publicvoidMap(boolreadOnly)
{
unsafe
{
if(IsMapped)
{
return;
}
if(readOnly)
{
_VirtualAddress=AweApi.VirtualAlloc(null,Capacity,AweApi.MEM_RESERVE|AweApi.MEM_PHYSICAL,
AweApi.PAGE_READONLY);
}
else
{
_VirtualAddress=AweApi.VirtualAlloc(null,Capacity,AweApi.MEM_RESERVE|AweApi.MEM_PHYSICAL,
AweApi.PAGE_READWRITE);
}
if(_VirtualAddress==null)
{
thrownewAweStreamException("Cannotreservememory.",AweStreamException.Reason.CannotReserveMemory);
}
if(!AweApi.MapUserPhysicalPages(_VirtualAddress,_NumberOfPages,_PFNArray))
{
AweApi.VirtualFree(_VirtualAddress,Capacity,AweApi.MEM_RELEASE);
_VirtualAddress=null;
thrownewAweStreamException(string.Format("MapUserPhysicalPagesfailed({0})",General.GetLastError()),
AweStreamException.Reason.MapUserPhysicalPagesFail);
}
_CanWrite=!readOnly;
}
}
去映射和归还AWE内存的过程是上面两个过程的逆过程,这里就不再多讲,有兴趣可以看我的代码。
下面是实例代码下载位置
源代码地址
分享到:
相关推荐
一个有效的实现.Net程序突破内存2G访问限制的程序源代码。
移动设备.NET应用程序设计源码 移动设备.NET应用程序设计源码
可以实现超大文件上传,但是不能断点上传。
该程序是关于ADO.NET Windows Froms应用程序的示例,包含如何通过ADO.NET连接数据库,对数据库表进行操作,有ExecuteReader,ExcuteNonQuery,ExecuteScalar,DataAdapter,Transaction,Dataset的使用,对理解,掌握与...
Vs2010测试时可以正常访问网络文件夹,\\192.168.2.249\d$\IndexRoot 但配置到IIS上就无法访问了,原因是asp.net development server具有最高的权限,可以通过本机存储的unc...于是,解决这个问题就有突破口了……
关于ASP.NET应用程序性能测试,在对ASP.NET应用程序进行性能测试之前,应确保应用程序没有错误,而且功能正确。具体的性能测试可以采用以下工具进行: Web Application Strees Tool (WAS)是Microsoft发布的一个免费...
ASP.NET应用程序,程序开发,语言,ASP,.NET 视频教程 希望网友们可以用上
asp.net 应用实例
vb.net关闭应用程序的代码 本例是关闭QQ的代码 关闭其它应用程序只要稍改一下就可以
.net 程序减少系统内存
自动化测试.NET WEB应用程序的性能测试
8.3ASP.NET应用程序中的用户状态管理 8.3.1Global.asax文件概述 8.3.2Application对象事件 8.3.3Session对象事件 8.3.4其他几种客户端的用户状态管理方法 8.3.5本小节提示 8.4ASP.NETHTFP运行情况 8.4.1HTYP运行‘晴...
用 .NET Memory Profiler 跟踪.net 应用内存使用情况--基本应用篇 .NET Memory Profiler 跟踪.net 应用内存使用情况--基本应用篇
第13章:本章详细的讲解了ASP.NET应用程序的内置对象和缓存等概念,ASP.NET的内置对象维护了Web应用程序的状态,而通过使用缓存能够极大的提高应用程序的抗压性,提高网站的访问效率。 第14章:本章详细的讲解了ASP...
.NET Memory Profiler是一款强大的.net 内存...该工具目前可以对一下4种.net应用进行内存跟踪。 基本应用 例如winform, console application等 ASP.net 应用 WPF应用 Window 服务 5.6官方最新版,支持netcore
VB.Net 应用教程.chm
.net4.0新增内存共享功能,从而很方便的实现了多进程间通信。
.net 创立一个分布式web 应用程序
Microsoft.Net Framework为应用程序访问Internet提供了分层的、可扩展的以及受管辖的网络服务,其名字空间System.Net和System.Net.Sockets包含丰富的类可以开发多种网络应用程序
MemoScope.Net 转储和分析.Net应用程序内存维基请阅读以了解有关MemoScope的所有信息。 许多图片,GIF动画和一些用于每个主要功能的文本。TLDR它的MemoScope.Net是什么? 它是分析.Net进程内存的工具:它可以将应用...