我正在Windows环境下为PCI开发一个驱动程序。我使用Windows7和Windows10,HW是i7-7700K,内存:16 16GBytes。
到目前为止,使用最多分配的2GBytes缓冲区没有问题。但是,没有分配超过2GB的内存。
下面是成功分配2GB dma公共缓冲区的代码片段。
DEVICE_DESCRIPTION dd;
RtlZeroMemory(&dd,sizeof(dd));
dd.Version = DEVICE_DESCRIPTION_VERSION;
dd.InterfaceType = InterfaceTypeUndefined;
dd.MaximumLength = 0x200000;// 2MB一次DMA传输大小
dd.Dma32BitAddresses = FALSE;
dd.Dma64BitAddresses =真;
dd.Master =真;
pdx->AdapterObject = IoGetDmaAdapter(pdx->Pdo,&dd,&nMapRegisters);
pdx->vaCommonBuffer = (*pdx->AdapterObject->DmaOperations->AllocateCommonBuffer) (pdx->AdapterObject,0x80000000,&pdx->paCommonBuffer,FALSE);
DMA公共缓冲区分配的大小限制是多少?为什么?
如果将长度0x80000000 (2GB)更改为0xC0000000 (3GB),则会导致缓冲区分配失败。如何使用AllocateCommonBuffer()分配最多4GB和超过4GB的dma公共缓冲区?
非常感谢您宝贵的时间和意见,提前。
尊敬的KJ
发布于 2022-08-10 21:43:20
我相信DMAv2 (这是最好的Windows 7支持)在一次分配中不能超过4GB,所以是的硬限制。
但是即使在达到硬限制之前,您也会开始看到不确定的分配失败,因为AllocateCommonBuffer为您提供了物理上连续的页面。
作为一个思想实验:它只需要8个不可移动的页面放置在病理上不方便的位置,然后在16 2GB的RAM中找不到2GB的连续页面。一个真正的系统将会有超过8个不可移动的页面,尽管希望它们不会在如此不幸的时间间隔中被放置。
更重要的是,DMAv2拒绝分配跨越4GB边界的内存(出于历史原因)。因此,在分配开始的3,670,017个不同页面中,有50%甚至没有考虑到。在3GB时,没有考虑到75%的可能分配。
多年来,我们在DMA子系统上做了很多工作: DMAv3是一个功能更强大的API,很少有奇怪的地方。它在Windows 10及更高版本中的实现具有一些抗碎片特性,并且内核的内存管理器在移动页面方面更好。这并不能消除支离破碎的根本问题,但它确实降低了统计上的可能性。
操作系统的最新版本实际上可以利用IOMMU (如果可用和启用的话)来进一步缓解这个问题:如果我们只需要使用IOMMU使它们看起来与设备相邻,那么您就不需要物理页面成为连续的了。( MMU正是用户模式应用程序在通过malloc
分配大量缓冲区时不需要担心物理内存碎片的原因)。
但是,在一天结束时,您不能简单地假设系统有任何2页连续的内存供您的设备使用,特别是当您需要您的设备在各种各样的系统上运行时。我见过带有oodles RAM的生产系统通常无法分配64 to的公共缓冲区,这“仅仅”是16个连续的页面。你需要:
https://stackoverflow.com/questions/73290091
复制相似问题