您的位置:首页 > 其它

让.Net 应用程序突破2G的内存访问限制

2008-11-06 14:00 344 查看
让.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 位地址空间所支持的内存量。

byte[] inputBuffer = new byte[1024];

Stopwatch stopWatch = new Stopwatch();

using (AweStream.AweStream aweStream = new AweStream.AweStream(1024 * 1024 * 100))

我在 6G内存 windows 2003 企业版的环境中做了测试,申请内存到5G以上没有任何问题。

下面再看看如何来申请AWE内存

下面的AweStream构造函数完成了对AWE内存的申请过程。

整个申请过程分为下面几步

1、为当前进程申请锁定内存的权限(注意 调用进程的帐号必须具备锁定内存的权限,否则这一步会失败)

2、就是需要申请的页面数量

3、通过 AllocateUserPhysicalPages API 申请AWE内存

public AweStream(UInt32 capacity)

AWE内存申请完毕后并不能被立即访问到,我们必须将其映射到32位内存地址中才可以访问。

下面是内存映射的代码:

也很简单:

首先先通过VirtualAlloc函数申请一块32位虚拟内存区域

然后通过 MapUserPhysicalPages API 函数将AWE内存映射到这个虚拟内存地址区域。

public void Map(bool readOnly)

{

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)

{

throw new AweStreamException("Cannot reserve memory.", AweStreamException.Reason.CannotReserveMemory);

}

if (!AweApi.MapUserPhysicalPages(_VirtualAddress, _NumberOfPages, _PFNArray))

{

AweApi.VirtualFree(_VirtualAddress, Capacity, AweApi.MEM_RELEASE);

_VirtualAddress = null;

throw new AweStreamException(string.Format("MapUserPhysicalPages failed ({0})", General.GetLastError()),

AweStreamException.Reason.MapUserPhysicalPagesFail);

}

_CanWrite = !readOnly;

}

}

去映射和归还AWE内存的过程是上面两个过程的逆过程,这里就不再多讲,有兴趣可以看我的代码。

下面是实例代码下载位置

源代码地址
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: