增加 Linux 内核模块 kfifo_alloc() 的大小,该模块失败 128MB

Increasing size for Linux kernel module kfifo_alloc() which fails for 128MB

提问人:Mehmet Fide 提问时间:11/16/2023 最后编辑:0andriyMehmet Fide 更新时间:11/17/2023 访问量:48

问:

我们有一个具有四核 Cortex-A53 内核的嵌入式产品,并运行 Linux 内核 v5.4 aarch64。整个 Linux 目前仅消耗 200MB 即可工作,因此我有足够的 RAM 可供使用。4 GB RAM

我制作了一个内核模块,它通过 PCIe 总线从外部设备读取 20MB/秒的数据,块为 1MB。我想将中断上下文中的这 1MB 数据推送到内核模块中的 FIFO 工作,以便稍后传输到用户空间。

我在 Linux 内核中寻找可用的 fifo 模式,并看到了它已经提供的一堆 API。这完全符合我的目的。据我了解,它支持单生产者和单一消费者方法,无需任何锁定。kfifo_alloc()put and get data

我的应用程序所需的 FIFO 大小应该在 128MB 左右。我已经有 4GB RAM,因此我最初认为分配这样的内存应该没有问题。

但是以下代码意外返回错误ENOMEM

ret = kfifo_alloc(&io_dev.streaming_dma_fifo, 128 * 1024 * 1024, GFP_KERNEL);
if (ret) {
    dev_err(&pci_dev->dev, "%s:error kfifo_alloc, ret=%d\n", __func__, ret);
    return ret;    
}

然后我搜索了 stackoverflow,看到人们使用抱怨同样的事情。我认为函数内部也使用.kmalloc()kfifo_alloc()kmalloc()

然后我按照这个论坛的建议再次执行了以下代码:

dev_info(&pci_dev->dev, "KMALLOC_SHILFT_LOW:%d, KMALLOC_SHILFT_HIGH:%d, KMALLOC_MIN_SIZE:%d, KMALLOC_MAX_SIZE:%lu\n", KMALLOC_SHIFT_LOW, KMALLOC_SHIFT_HIGH, KMALLOC_MIN_SIZE, KMALLOC_MAX_SIZE);

并为我的系统提供了这些输出:

KMALLOC_SHILFT_LOW: 7
KMALLOC_SHILFT_HIGH: 13
KMALLOC_MIN_SIZE: 128
KMALLOC_MAX_SIZE: 33554432

我从这个输出中了解到的是,我可以分配的最大大小限制为 .kfifo_alloc()32MB

如果我尝试将请求的大小从减小到 ,它不会返回错误。kfifo_alloc()128MB32MB

问题:

  1. 我的FIFO RAM没有任何特殊要求,例如它应该是连续的,原子的或DMAable的或其他东西。我不明白为什么 kfifo_alloc() 以 128MB 失败,而我可以轻松地在用户空间中分配相同的数量。有没有办法要求使用或内核等价物,而不是特殊?malloc()kfifo_allocmallockmalloc

  2. 有没有办法将我的系统定义为 32MB 的KMALLOC_MAX_SIZE增加?

  3. 例如,将KMALLOC_MAX_SIZE设置为 256MB 会有什么后果?

  4. 如果我的驱动程序需要大于 32MB 的 FIFO,建议采用什么方法?

linux-kernel linux-device-driver kmalloc

评论

0赞 Ian Abbott 11/16/2023
您可以更改内核配置中的CONFIG_ARCH_FORCE_MAX_ORDER设置以更改MAX_ORDER常量。并非所有架构都允许配置它(特别是 x86,其中 MAX_ORDER 固定为值 10),但 arm/arm64 确实允许配置它。该值是可以分配的物理连续页数的对数基数 2,例如 13 允许分配 2^13 (8192) 个物理连续页或 2^13*2^12 (8192*4096 = 33554432) 个物理连续字节。
0赞 0andriy 11/17/2023
这种大小的连续内存分配应与通过 .对于 DMA,可以使用 CMA 和其他内存区域。因此,如果没有这些要求,人们可以简单地要求.仅供参考:从不保证分配超过单个页面(通常为 4k)的任何内容。kmalloc()vmalloc()kmalloc()
0赞 0andriy 11/17/2023
阅读更多有问题的细节,我相信你还没有得到背后的想法,kfifo等等,因此你的东西已经在设计层面上被破坏了。您需要的是将数据从设备复制到某个内存缓冲区(大概必须使用 DMA 完成),并且仅使用 FIFO 指向块并控制内存的占用。kmalloc()

答: 暂无答案