c#中的VirtualAlloc用于分配大内存

本文关键字:大内 内存 分配 用于 中的 VirtualAlloc | 更新日期: 2023-09-27 17:57:42

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

这很有效,但最终失败了,因为.Net在一个数组中被限制为大约20亿个元素。我可以通过使用Long和gcAllowVeryLargeObjects关键字的数组将限制提高到16GB,但最终我仍然会遇到.Net的限制。

在非托管代码中,我可以调用VirtualAlloc并直接请求40或50GB,但我不清楚这在c#中是否可行,我也找不到任何好的示例代码。我意识到我可以用另一种语言来做这件事,但至少在Windows上,我更熟悉.Net,除了这个相对较小的程序部分,很少有硬件特定的代码,所以我想尝试并坚持我现有的。

c#中的VirtualAlloc用于分配大内存

您可以pinvoke VirtualAlloc。签名是

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

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

或者,看看AllocHGlobal函数

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

在任何情况下,您都可以使用破解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,它确实应该做同样的事情(尽管除了大小之外,您不能指定任何参数)。