【发布时间】:2015-11-02 18:08:11
【问题描述】:
我正在开发一个涉及一些自定义硬件和我为硬件编写的自定义 Linux 设备驱动程序的系统。系统有时需要非常快速地移动大量数据,因此我的驱动程序会动态(即在需要时)分配大的 (1 GB) DMA 缓冲区,这些缓冲区被使用,然后在不再需要时释放。为了分配这么大的缓冲区,我实际上使用dma_alloc_coherent 分配了一堆较小的缓冲区(256 X 4MB),然后使用remap_pfn_range 将它们连续映射到用户空间。这在大多数情况下都非常有效。
在测试过程中,系统长时间运行测试用例后,我有时会看到 DMA 分配失败,我的驱动程序中的 dma_alloc_coherent 调用之一失败,导致我的应用层软件崩溃。我终于能够追查到这个问题,我发现当我看到 DMA 分配失败时,Linux 内核页面缓存非常满。
例如,在我上次捕获页面缓存失败时,系统上的 32 GB RAM 中的 27 GB 被我捕获。我怀疑页面缓存“充满”导致dma_alloc_coherent 调用失败。为了测试这个理论,我手动清空了页面缓存:
# echo 1 > /proc/sys/vm/drop_caches
这将缓存大小从 27 GB 降低到 94 MB,并且我能够毫无问题地分配 20+ 1 GB DMA 缓冲区。
显然,页面缓存是一件有益的事情,所以我不希望每次在分配 DMA 缓冲区时空间不足时都必须完全清空它。我的问题是:如何动态缩小内核空间中的页面缓存,以便如果对 dma_alloc_coherent 的调用失败,我可以恢复足够的空间,以便我可以重试调用并使其成功?
我的系统基于 x86_64,运行 3.16.x Linux 内核。
我发现了一些模糊的参考,暗示我正在尝试的可能是可能的,例如“这些对象是自动 当系统上的其他地方需要内存时由内核回收。”(来自:https://www.kernel.org/doc/Documentation/sysctl/vm.txt)。但我还没有找到任何表明内存是如何回收的细节。
对此的任何帮助将不胜感激!
【问题讨论】:
标签: linux memory-management linux-kernel linux-device-driver