c#中的VirtualAlloc分配大内存

时间:2014-04-09 07:20:35

标签: c# memory virtualalloc

我正在尝试调整供应商的c#示例代码,以便与PCI-Express设备连接。代码基本上将一个大缓冲区分配为一个int数组,然后通过fixed关键字将其固定,然后将其交给硬件以填充数据。

这很好用,但它最终失败了,因为.Net仅限于数组中大约20亿个元素。我可以通过使用Long和gcAllowVeryLargeObjects关键字数组将限制推高到16 GB,但最终我仍然遇到.Net限制。

在非托管代码中,我可以直接调用VirtualAlloc并请求40或50GB,但是如果在c#中这是可能的话我不清楚并且我还没有找到任何好的示例代码。我意识到我可以用不同的语言来做这件事,但在Windows上至少我比较熟悉.Net,除了这个程序的这个相对较小的部分之外,几乎没有特定于硬件的代码所以我&# 39;我想尝试坚持我拥有的东西。

2 个答案:

答案 0 :(得分:5)

您可以对VirtualAlloc进行pinvoke。签名是

[DllImport("kernel32.dll", SetLastError=true)]
static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize, AllocationType lAllocationType, MemoryProtection flProtect);

您可以在pinvoke.net上找到大多数pinvoke结构和签名:VirtualAlloc

或者,看一下AllocHGlobal func

答案 1 :(得分:1)

gcAllowVeryLargeObjects应该可以正常工作,你确定它没有吗?您可能必须将目标CPU明确设置为x64。

在任何情况下,您都可以使用hack struct来获取一个大值类型(可以用作数组):

unsafe struct Test
{
  public fixed byte Data[1024];
}

unsafe void Main()
{
    Test[] test = new Test[16 * 1024 * 1024];

    // We've got 16 * 1024 * 1024 * 1024 here.
    fixed (Test* pTest = test)
    {

    }
}

这确实有其局限性(不安全的结构具有最大尺寸),但它应该可以让你到达你需要的位置。

然而,简单地通过P / Invoke调用VirtualAlloc可能更好。或者更好的是,使用Marshal.AllocHGlobal,它应该做同样的事情(尽管除了大小之外你不能指定任何参数)。