2

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

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

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

4

2 回答 2

7

您可以调用 VirtualAlloc。签名是

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

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

或者,看看AllocHGlobal函数

于 2014-04-09T07:37:17.850 回答
1

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

在任何情况下,您都可以使用 hackstruct来获得较大的值类型(您可以将其用作数组):

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)
    {

    }
}

这确实有它的限制(不安全的结构有一个最大尺寸),但它应该能让你到达你需要的地方。

但是,最好VirtualAlloc通过 P/Invoke 简单地调用。或者更好的是, use Marshal.AllocHGlobal,它确实应该做同样的事情(尽管您不能指定除大小之外的任何参数)。

于 2014-04-09T07:50:59.107 回答